← SailPoint ISC Greenfield Implementation Field Guide

SailPoint ISC Greenfield Implementation Field Guide

The HR Authoritative Source and Identity Model

Everything ISC does to people starts with the authoritative source. On this program the HR system was the only real one, and the identity model built on it carried 60-odd attribute mappings, 40-odd transforms and a handful of cloud rules. Get this layer right and joiner, mover and leaver mostly behave. Get it wrong and every other page of this guide turns into firefighting.

Choose the authoritative source on purpose

  • One authoritative source for the workforce. A second profile existed only for a few administrator identities loaded from a delimited file with no cluster. Keep secondary profiles tiny and give them a lower priority number than the main one so correlation stays predictable.
  • The HR system must carry what automation needs. If lifecycle automation needs a disable date, a time zone, a manager identifier or a reason for leaving, those fields must exist in HR and be mandatory. We added several integration-specific fields to the HR object: a disable-access date, an employment status flag for the identity system, a reason for leaving, the work location time zone, a last-modified timestamp, and fields to hold the email address and login name written back by ISC.
  • Mandatory means enforced. The design assumed the disable date and leave date were mandatory. Hypercare then produced cases where HR forgot to update the disable date, or entered the wrong last day, and the account stayed live or was cut early. Put validation in the HR system, not in a document.

Connecting a Salesforce-based HR system (Sage People)

The HR system was Sage People, which runs on Salesforce. The ISC Web Services connector talked to its REST query API.

AspectWhat we didWhy it matters
AuthenticationOAuth token endpoint called by a custom authentication step; the token is mapped into the source and sent as a bearer headerCredentials for the token call end up in the endpoint body, so check how the source stores them (see the security page)
QueryA SOQL query over the team member object joined to current employment, selecting around 40 fieldsSelect only what you map. Every extra field slows the sync and widens the blast radius of a rename
PagingTermination step reads the done flag and follows nextRecordsUrl until finishedWithout correct pagination steps the connector reads one page and stops
ScheduleHourly, all 24 hoursJoiners and leavers react within an hour. The design promised hourly sync from day one
Timeout200 secondsThe first full load is large; size the timeout for it
DeltaA delta query filtered on a last-modified field existed in the legacy designDecide deliberately whether you use delta. Delta reads usually cannot detect records that disappeared, so even with delta you need periodic full aggregations
Test connectionA query with a hard LIMIT 2Confirms the credential and endpoint only. It does not validate your projection

Writeback to the HR system (email address, login name) used a PATCH to the same object. It is covered below.

The join key

The design pinned the whole lifecycle to one HR field: the unique employee identifier, stable for the whole journey of a person including leaving and rehire. Everything keys on it.

ConceptRule
JoinerAn identifier ISC has never seen, with status Active or Pre Joiner
MoverAn identifier ISC already has, with any change in a mapped attribute
LeaverAn existing identifier whose disable-access date is today or in the past, whatever the employment status says
RehireAn existing identifier returning to Active or Pre Joiner with an empty reason for leaving

The rehire rule is an HR process, not an ISC feature

The platform cannot decide whether someone is a rehire or a new person. The program put a rule on HR:

  • Back within 6 months, same location and department: reuse the old identifier. ISC reactivates the old account.
  • Back within 6 months into a different department or location, or after 6 months in any case: HR creates a new record with a new identifier. ISC creates a new identity, a new login and a new mailbox.

The reason was data protection. In one case an ex-employee moved between countries and wanted to keep the old mailbox, which held another entity's client data. Reactivating the old account would have exposed it. The 6-month rule was written into the risk log as the mitigation and communicated to HR, and it still produced hypercare tickets from regions that had not got the message.

Identity attribute mapping

  • The profile mapped account attributes straight across (names, department, title, country code), referenced transforms for anything that needed cleaning, and called cloud rules for computed values.
  • Directory identifiers were also read back in from the target accounts (login name, mail, distinguished name of the user and the manager) so later steps could build on them.
  • Manager is correlated by comparing the manager's HR identifier to each identity's own identifier; for directory accounts the built-in manager correlation by account ID was used.

Transforms: use lookups, not nested conditionals

The legacy tool normalised location and country names with enormous nested IIF(Eq(...)) expressions: more than fifty location rewrites in a single expression, plus employee-type mappings. Replacing those with ISC lookup transforms was one of the best decisions of the build.

The transforms that were worth having:

PurposeExamples
NormalisationRemove diacritical marks, trim, spaces collapse, lower and upper case
Standards formatsE.164 phone, ISO 3166 country, RFC 5646 language, ISO 8601 date
LookupsCountry name, location name, office location code, RDC maps, employee type
Per-country contactsHR contact, finance contact, local IT contact, driven by country or location lookups
Directory buildersActive and disabled distinguished names, login name, mail nickname
Date logicIs the hire date today, past or future; is now past the end date

Caveats:

  • Lookup tables hold business data inside the tenant. HR contacts, finance contacts and local IT contacts per country live in transform tables. They change monthly. Agree an owner, a delivery channel (we used a monthly file from HR) and a change procedure, or contacts go stale and mails go to people who left. Several hypercare tickets were exactly this.
  • Transforms reference transforms. A directory DN transform referenced a location lookup that referenced a trim. Test the chain with real values, including blanks.
  • A "default" on every lookup. A location missing from the table otherwise yields an empty value and, downstream, an account in the wrong container or none at all.
  • Keep a naming scheme. We had separate "on identity profile" and "SP" variants of several DN transforms. Pick one set and retire the rest, or you will edit the wrong one.

Cloud rules that compute identity attributes

Cloud rules run inside ISC with no network access. The program used them for values that need real logic.

RuleComputesNotes
Lifecycle state generatorThe cloudLifecycleState attribute from HR status, end date and time zoneSeveral variants (temp, latest, extended) existed in the tenant. Only one is referenced by the profile; the rest are clutter and a trap
Next processing dateThe moment, in UTC, at which the identity's end date is reached at 22:00 local timeUsed by schedule-driven leaver workflows
Login name generatorThe sAMAccountNameDescribed below
Mail generatorThe email addressDescribed below
End-date eligibilityA flag for a SaaS payroll app's half-month disable scheduleShows how business calendars end up in rules

Things to know about cloud rules:

  • You cannot read them back through a normal GET. To see the code you export configuration (a single export call limited to the rule type), which creates an export job. Treat that as part of discovery.
  • Changes may go through SailPoint. In the early build the tracker recorded a "rules upload ticket opened with SailPoint, awaiting review and upload". Ask what the current process and turnaround are for your tenant, and build that into the plan.
  • No network, no model. A cloud rule cannot call an external service, so anything needing a lookup against another system has to run in a workflow or a connector rule.
  • Delete the variants. Four near-identical lifecycle rules and two next-processing rules sat in the tenant. Keep one, name it plainly, and archive the others outside the tenant.

How the lifecycle rule thinks

The core of the generator is worth copying as a pattern:

java
// Treat the end date as 00:00:01 on the day, move it to the person's own time zone, and
// pin it to 22:00 local. Compare with "now" in UTC at hour precision.
endDateLocal = endDate.withZoneSameInstant(ZoneId.of(tz)).withHour(22).truncatedTo(ChronoUnit.HOURS);
endUtc       = endDateLocal.withZoneSameInstant(ZoneId.of("UTC"));
nowUtc       = ZonedDateTime.now(ZoneId.of("UTC")).truncatedTo(ChronoUnit.HOURS);

if (!nowUtc.isBefore(endUtc) && !status.startsWith("Inactive")) return "inactive";
if (status.equalsIgnoreCase("Active"))      return "active";
if (status.equalsIgnoreCase("Pre Joiner"))  return "preJoiner";
if (status.startsWith("Inactive"))          return "active";   // paid or unpaid leave stays active
return "intermediate";

Design points that carry over:

  • A far-future default end date (year 9000) avoids null handling.
  • An invalid or missing time zone falls back to a sensible default rather than throwing.
  • Hour-level truncation makes the comparison deterministic for a rule that is recomputed on every refresh.
  • Leave statuses are not leavers. Paid and unpaid leave kept the identity active.
  • Log the inputs. The rule logs every input to every condition. That is verbose but it is the only way to explain a state change later.

Login names, emails and distinguished names

Joiner automation generated three identifiers. The rules are small and every one of them produced hypercare tickets.

IdentifierRuleCaveat
Login nameFirst 3 letters of first name + last 3 letters of last name + a two-digit counter, 8 characters maximumThe counter increments until idn.accountExistsByDisplayName says it is free. We capped the loop at 2,000 attempts. Short names are padded with random letters
Emailfirst.last, then first.last1, first.last2... on collisionChecked against the directory, not only ISC. Name changes generate a new address; the old one becomes a secondary alias
Distinguished nameCN + region / department / work location pathThe CN is the login name, so the directory's "Name" shows ABC123 rather than a human name

That last point caused several tickets: after the cutover date, new users appeared in the directory console under their login name. The explanation that worked for service desks: the directory's Name attribute defaults to the CN, display name is a different attribute and is still the human name, Outlook and Teams use display name, and for audit reports you should export display name, CN, login name and Name together. Publish that note before go-live.

Display names

  • Double spaces. A name attribute built from a directory CN gave "First Last" for people without a middle name. Normalise with a collapse-spaces transform and search with that in mind.
  • Maiden names. If HR's full name includes a maiden name and you split it, you get "First Last Last". Build the display name from first name and last name only, and keep a separate attribute for the app that needs a different format.
  • Requested name changes. HR corrects a surname and expects a new email: that is a mover with a name change, handled by the directory before-provisioning logic (new address, UPN, SMTP and SIP proxy addresses, old SMTP kept as an alias). It needs to push the new address back to HR.

Writeback to HR

Email and login name must be written back to the HR system so downstream systems and HR users see them. The pattern that worked:

  1. Event-driven workflow fires on a change of the email or login name attribute (ignoring the literal value none), waits briefly, then PATCHes the HR record.
  2. Scheduled workflow runs twice a day and sweeps for identities whose values are not yet in HR, so a failed event is repaired automatically.
  3. Both send a notification on failure.

Caveats from the program:

  • The HR OAuth call used a password grant, and the workflow HTTP step held the client secret in the body in plaintext. ISC lets you reference a stored secret in a workflow, but the secrets can only be created in the UI. Do that, not the plaintext version. See the workflows and security pages.
  • HR users kept asking "please push the work email into the HR system" for pre-joiners. The scheduled sweep exists because the event path is not perfect; tell HR the sweep interval so they know when to expect it.
  • Name corrections after the email was written back arrived as support requests ("push the new work email"). Decide who owns that path and whether it can be automated.

Correlation

Account-to-identity correlation was attribute-based on almost every source. Conventions that emerged:

Source typeTypical sequence
Directorylogin name, then email
Application with login = emailemail only
SQL applicationslogin name, then email, then employee number
Mixedemail, then login name, then employee number

Rules that follow from this:

  • Correlation is case sensitive unless you say otherwise. An email that differs only in case does not correlate, and the account lands in the uncorrelated pile rather than showing a mismatch. Set ignoreCase deliberately.
  • A single-attribute correlation with no fallback is fragile. An identity with no email cannot correlate at all.
  • Never correlate on a synthesised display name. One source built userName from first and last name in an after-rule; it was a display field, not a login.
  • Align correlation and provisioning. The attributes you correlate on should be the same ones the create policy writes, otherwise a freshly created account fails to correlate.
  • Plan for uncorrelated accounts. Access reviews need a source-owner campaign for them (see the campaigns page).

Data reconciliation before cutover

A pre-go-live reconciliation of directory accounts against HR found well over a thousand active directory accounts with no employee ID, plus a long tail of other mismatches (accounts for people HR no longer had, staff on unpaid leave, service-like accounts in human OUs). Do this analysis early:

  1. Export directory accounts and HR records. Compare on employee ID, then email, then name.
  2. Classify: matches, directory-only, HR-only, duplicates, non-human accounts in human OUs.
  3. Agree a remediation owner and a deadline for each class. Backfilling the employee ID attribute in the directory is a legitimate one-off to enable correlation.
  4. Define the standard human-account OU scope so the directory aggregation excludes service and shared accounts.

What SailPoint's documentation adds

From the identity profile documentation, the account loading documentation and community threads on correlation and authoritative-source migration, checked October 2026.

Identity profiles

  • One identity belongs to one profile, the highest-priority profile where it has an account on that profile's authoritative source. Priority follows creation order (10, 20, and so on) and can be changed through the update-identity-profile API. Plan the order before you create overlapping profiles.
  • Required mappings: user name, work email and last name must be mapped in every profile and cannot be null. User name must be unique across identities; a duplicate raises an identity exception.
  • Do not use the characters * ( ) & ! . in the source attribute mapped to the user name or alternative sign-in attribute.
  • A multi-value attribute in a transform uses only its first value. Test with a person who has two.
  • You cannot create or delete an identity profile while an account aggregation is running.
  • Deleting a profile deletes its identities unless they can be reassigned, and their accounts become uncorrelated. Remove source-owner and app-owner links from those identities first, or the deletion fails.
  • After changing mappings the profile shows "Needs Processing". Apply the changes, and use Preview on the mappings page with real data first.
  • Rules need review by SailPoint before implementation; transforms do not. This is why a rule change can take calendar time.

Optimized aggregation and correlation

Optimized and unoptimized aggregationAn optimized run skips unchanged accounts and does not re-run correlation. An unoptimized run reprocesses everything.Optimized (default, UI and schedules)Read everyrecordfrom the sourceChanged sincelast run?Skip the accountno correlation, nomanager correlationUpdate attributesevaluate correlationand managercorrelationnoyesUnoptimized (API only)load-accounts withdisableOptimization=truethat one run onlyEvery record is processedcorrelation re-run for allManually correlated accountsare keptcheck them before you start
Why a fixed correlation rule can do nothing. Accounts that did not change are skipped, so they are never re-matched. Use the unoptimized run after correcting correlation logic or the data it matches.

This is the most useful addition to the correlation section above. By default an aggregation is optimized: it reads every record, but an existing account with no detected change is skipped and neither account correlation nor manager correlation is evaluated for it. Consequences:

  • Fixing a correlation rule, or fixing the data it matches on, does not re-correlate accounts that did not change. Accounts stay uncorrelated until you run an unoptimized aggregation.
  • Scheduled and manual runs from the UI are always optimized. An unoptimized run is available only through the API, by passing disableOptimization=true to the account-load call, and it applies to that run only.
  • Manually correlated accounts are kept on an unoptimized run, so check for them before you start.

Community practice for changing correlation: confirm the new attribute is populated, unique and immutable on every existing account, add it as the first criterion with the old one as a temporary fallback (criteria are evaluated in order), run the unoptimized aggregation, then review what is still uncorrelated. Community threads also report a default fallback that compares the account name with the identity name when no configured criterion matches, which can correlate an account you did not expect. Treat that as observed by others, not documented.

One identity belongs to one identity profileAn identity joins the highest priority profile whose authoritative source holds one of its accounts.Person Aaccount on the HR source onlyPerson Baccounts on the HR source andon the admin sourceHR profile, priority 20authoritative source: HRsystemAdmin profile, priority 10authoritative source: smalladmin filehighest priority winsIdentity in the HRprofilemappings and lifecycle ofthe HR profileIdentity in the adminprofilemappings of the adminprofilePriority follows creation order by default (10, 20,...). Lower number wins. Change it with the update profile API.
Priority matters for second sources. Plan the order before you create overlapping profiles; you cannot create or delete a profile while an account aggregation is running.

Choosing the join key

Both the documentation and the community's authoritative-source migration guide say the same thing we concluded: use an attribute that is unique, consistently captured in every system and immutable, and avoid personally identifiable values such as government identifiers.

Replacing or changing the HR system

SailPoint's migration guide gives a sequence worth adopting if the HR platform will change during or after your program:

Replacing the HR system without a big bangNine steps: move the HR system first, onboard it separately, mirror the identity profile, migrate access-driving attributes last.Go live with the new HR system firstnot the same day as the ISC switch. Watch the data for days, pause orchestrations1Onboard the new HR sourcelet several aggregations run, configure manager correlation2Correlate to existing identitieson the agreed unique attribute. Review the uncorrelated report3Create a mirrored identity profilesame mappings and transforms. Confirm identity counts4Raise its prioritycheck identities moved: counts, search, spot checks5Update role criteriaadd OR clauses so people qualify on old or new HR data6Migrate attributes graduallyfirstValid transforms. Lifecycle state and other access-driving attributes last7Re-point owners and groupsgovernance groups, source owners, application owners8Clean updelete the old profile, optionally the old source9
Sequence from SailPoint's authoritative-source migration guide. Choose a low-impact window and keep a rollback plan with time to execute it.
  1. Go live with the new HR system first and do not switch ISC to it the same day. Pause orchestrations and watch its data for a few days to a week.
  2. Onboard the new HR source, let several aggregations run and configure manager correlation.
  3. Correlate its accounts to existing identities on the agreed unique attribute and review the uncorrelated report.
  4. Create a new identity profile mirroring the old mappings and transforms, confirm identity counts, then raise its priority.
  5. Update role criteria with OR clauses so people qualify on either the old or new HR data.
  6. Migrate attributes gradually with firstValid transforms, moving lifecycle state and other access-driving attributes last.
  7. Re-point owners and governance groups, then delete the old profile.

Actions

  • Specify the HR fields automation needs and enforce them in HR.
  • Document the join key and the rehire rule and get HR's written agreement.
  • Replace conditional-heavy mappings with lookup transforms that have defaults, and name an owner for every table.
  • Keep one version of each cloud rule; export and archive the rest.
  • Publish the CN-equals-login-name explanation to service desks before go-live.
  • Reconcile directory accounts to HR at least a month before cutover.