Automatic reassignment

Last modified by Antonín Otmar on 2026/09/22 10:05

Information

This page describes a family of features. It explains what they do, what they share and how they differ; each
implementation is documented in detail on its own page:

What the features solve

There are several things in IdStory that a particular entity is responsible for: somebody guarantees a contract, somebody guarantees a role, somebody has an approval task to approve or disapprove. It is a common issue that upon the deletion or deactivation of this entity, whatever they were responsible for becomes silently orphaned which will only be found much later. 

The automatic reassignment feature close this hole. When the last active holder of a responsibility is removed or deactivated, a substitute holder is resolved and assigned the responsibility, so it doesn't become orphaned.

Every implementation follows the same four steps:

  1. Detect - a change makes an identity stop being an active guarantor, and that identity was the last active identity responsible for the object.
  2. Resolve - the substitute(s) are resolved by a configurable system script, with a fallback chain that always ends with somebody.
  3. Assign - the substitute becomes a responsible for the object.
  4. Notify - the substitute receives one consolidated message listing everything they took over and why.

Examples:

  • The sole guarantor of a guarded externist's contract is deactivated via an HR process - the contract is handed to the departing guarantor's manager.
  • A team lead who is the sole guarantor of several application roles leaves the company and their identity is deleted - the guarantees move to their manager.
  • An external consultant's contract expires; they were the only holder of a guarantee role used by ten business roles - the guarantee role is reassigned to the manager reachable through that contract.
  • The only approver of a running approval task is deactivated - the task is reassigned, so the request waiting behind it can be decided.

What the features have in common

Only the last active identity matters

Nothing happens if an identity becomes invalidated while somebody else still keeps responsibility for the object. An identity that becomes inactive simply stops counting as responsible, and if another active identity remains, no substitute is resolved, nothing is assigned and no notification is sent.

The resolution chain always ends with somebody

The features resolve the substitute in a way that guarantees a result - that the guarded object is never left without an identity responsible is the business rule, so it does not depend on the configuration being complete:

  1. The configured system script. Only results that are identities and are active (state VALID, not disabled) are kept, and never the departing guarantor themselves. A non-empty result wins.
  2. The active holders of the configured fallback role. Used when the script returns nothing, returns the wrong type, fails, or is not configured at all. When the fallback role is not configured - or names a role that does not exist - the admin role (idm.sec.core.role.admin, superAdminRole by default) is used in its place.
  3. The admin identity. The last resort, when the role above has no active holder either.
Error

The consequence is that an installation that switches a feature on without configuring a fallback role hands the responsibility to its superadmins whenever the script resolves nobody. Configure the fallback role before you switch anything on.

Managers are the default answer

The scripts shipped with the features resolve the managers (superiors) of the departing identity. They therefore depend on how manager resolution is configured in the installation - the managersFor filter implementation (idm.sec.core.filter.IdmIdentity.managersFor.impl) decides this. When managers are not the right answer (i.e. we want to fall back onto a fixed support team, a role or a named list) it is possible to write a custom script.

For the correct functioning of some of the listed features, as well as the correct functioning of IdM in general, it is necessary to make sure that the subordinatesFor (idm.sec.core.filter.IdmIdentityContract.subordinatesFor.impl) filter is the appropriate counterpart of the managersFor filter, i.e. if the managers filter ignores tree structures, the subordinates filter should ignore them as well and vice versa.

The shipped scripts are templates

Error

The scripts shipped with the product are templates. Redeploying a script from disk - the Redeploy action, or a product upgrade - restores the body shipped with the product and silently throws away everything that was edited in it. If you want to avoid that, duplicate the script, save the copy under a code of your own, edit the copy and point the feature's script configuration at the copy.

Deliberate manual changes are respected

None of the features react when an administrator removes a guarantorship by hand - an IdmContractGuarantee deleted or changed, a direct role guarantee removed, a role's guarantee role link removed. A manual removal is an explicit decision that the object should not have that guarantor, and reassigning a substitute immediately afterwards would make it impossible to carry out.

Objects on their way out are skipped

When the guarded object - or its owner - is being (force) deleted, it is flagged with the DELETED entity state and the reassignment features step aside. Transferring the guarantorship of something that is about to disappear makes no sense.

The reassignment only ever adds

Error

⚠️ Undoing the triggering change does not undo the reassignment. When a guarantor is unblocked, a contract is included again, or an identity is restored, the original guarantor becomes active once more - but the substitute stays. At that point, there is no way to differentiate between a guarantor assigned as the substitute and any other guarantor. If the object should have the original guarantor only, remove the substitute by hand.

One consolidated notification per new guarantor

The features which notify the substitute identity send one message per new substitute, not one per guarded object: whatever a single batch hands to the same substitute arrives as a single message listing everything at once. The message names the original responsible identity and carries a reason code saying what happened, so the recipient learns not only what they took over but why. The notification template gets the following parameters:

ParameterMeaning
identitythe new guarantor (the recipient)
originalGuaranteethe guarantor who is no longer active
reasonthe reason code of the triggering event
(the guarded objects)

see the details of each particular implementation

HR processes

Contract validity elapsing by date raises no event of its own, so the nightly HR long running tasks are what turns an expired contract into a reassignment by emitting the identity deactivation event.

Main differences between the implemented reassignment features

 Contract guarantorRole guarantorApproval task approver
Available@since 15.18.0 (not released)@since 15.17.0@since 15.18.0 (not released)
KeepsIdentity contracts guaranteedRoles guaranteed - direct guarantees and guarantee rolesRunning approval tasks approvable
SwitchOff by default (idm.sec.core.contract-guarantee.enabled) and inert until the guarded projections are configuredAlways on, no switchAlways on, no switch; the processor is not disableable either
ScopeOnly identities with a configured form projectionEvery role that has a guarantorEvery running approval task
TriggersThe guarantor identity is deleted or deactivatedIdentity delete / block, contract delete / deactivation / exclusion / expiry, loss of the guarantee role assignmentThe approver identity is deleted, or transitions into a disabled state
TimingAsynchronous, through its own eventSynchronous, in the BEFORE phase of the triggering eventAsynchronous, as part of identity event processing
TransactionIndependent of the triggering transactionAtomic with the triggering operation; a failed transfer aborts itIndependent of the triggering transaction
Original holderAlways removedKept for the reversible states (manual block, contract exclusion), removed for the destructive onesKept when deactivated (rendered grey, for history), removed when deleted
Script propertyidm.sec.core.contract-guarantee.fallbackScript (not configured by default)idm.sec.core.role.guarantee.transferScript (default roleGuaranteeTransferTargets)idm.sec.core.wf.approval.task.reassign.script (not configured by default)
Script inputidentity, guarantee, contract, guaranteeContracts, guaranteeManagersidentity, contractapprovalTask, lastApprover
Fallback role propertyidm.sec.core.contract-guarantee.fallbackGuarantorRoleidm.sec.core.role.substituteFallbackidm.sec.core.role.substituteFallback (shared)
Shipped scriptscontractGuaranteeFallbackTargets + two demo scriptsroleGuaranteeTransferTargets (the configured default)Three scripts, none configured by default
Default substituteManagers of the departing guarantorManagers / superiors of the departing guarantorThe fallback role holders - until a script is configured
Repairing historyBackfill task Assign fallback guarantor to guarded contracts, with dry runNoneNone - fix by hand with the Add approvers / Remove approvers bulk actions
Notifies the substituteYes - core:contractGuaranteeFallbackAssignedYes - core:roleGuaranteeTransferredNo - no new task notification is re-sent

Why the timing differs

  • The role transfer has to read the live data (the guarantees, the contract, the role assignments) that the triggering change is about to destroy, and it must not leave a role unguaranteed if the change is rolled back. It therefore runs before the change, inside its transaction - at the price of a failed transfer aborting the triggering operation.
  • The contract reassignment can be started by one deactivated manager with hundreds of subordinates. It therefore takes a snapshot of everything it needs, publishes its own event and runs asynchronously, so that nobody waits for it - at the price of the result only being visible once the event is processed.

Which one do I need

They are independent features guarding different objects, and an installation commonly wants both.

  • Turn on contract guarantor reassignment when a category of identities - externists, contractors, service identities - must never be left without somebody responsible for them. It is off by default and needs configuring before it does anything.
  • Role guarantor reassignment is on out of the box and needs no configuration to work; configure its script and fallback role when its managers-based default is not the substitute you want.
  • Approval task approver reassignment is on out of the box and cannot be switched off. Configure a script when the fallback role is too blunt an answer - the shipped managers of the last approver script is the usual choice.