Self-Service Group Management
Operator runbook for owner-managed Active Directory and Entra ID groups: an end user creates a group, other users ask to join it, the owner approves, and IdentityMesh provisions the result through its own connectors. Membership, ownership, expiry and the audit trail all live in the mesh; the directory is a target, not the master. This is the Microsoft Identity Manager (MIM) self-service group parity feature.
New in this release. Run the three round trips at the end of this runbook (create, approved join, delete) on a test directory before opening the portal to users, and treat the Entra (Graph) side as the part to watch most closely.
Also new: groups that already exist in Active Directory can now be brought under self-service management without being recreated. See Onboarding groups you already have, including the two acceptance groups to run first and the one known issue to read before applying the AD template on an estate that imports groups.
Before upgrading
This release changes what DeleteIfUnlinked does on a projection
rule. It is the one thing to read before installing, and it
affects every rule in the estate, not just self-service groups.
Before, a rule with Delete if unlinked ticked did nothing when an object’s precondition stopped holding: the export carried an empty change and every connector turned it into no modification. The flag was inert. Now the same configuration emits a real Delete, and the object is removed from the target on the first export drain after the upgrade.
Run this before the upgrade
Run this query in SQL Server Management Studio against the IdentityMesh database before you run the new MSI:
SELECT r.ProjectionRuleId, c.Name AS ConnectorName, r.MeshObjectType,
r.TargetObjectType, r.CreateIfMissing, r.DeleteIfUnlinked, r.PreconditionScript
FROM dbo.IM_ProjectionRules r
JOIN dbo.IM_Connectors c ON c.ConnectorId = r.ConnectorId
WHERE r.DeleteIfUnlinked = 1;
Every row is a rule that would now delete target objects. For each one, read its precondition and count how many objects it currently excludes: that is how many directory objects the first drain would delete. Keep the output as the record of the estate before the migration touched it.
What the upgrade does with them
The installer’s database step runs a one-time migration that clears
DeleteIfUnlinked on every existing rule and records which rules
it reset under the system setting Export:DeleteIfUnlinkedReset.
Re-tick the flag only on the rules where deleting the target object
is what you want.
- It runs once, ever. The guard is the marker row, so a later redeploy will not undo a deliberate re-tick.
- It does not touch the shipped templates. The two self-service group templates carry the flag on purpose: deleting the directory group is the point of deleting a self-service group.
- It does reset a rule you already applied from those templates. If you applied a group template on an earlier build, re-tick it, or self-service deletes will stop reaching the directory.
After the reset the Sync Engine logs one warning at startup for every rule that still carries the flag, naming the rule, its connector and both object types. That is your standing inventory of deletion paths.
How a group is modelled
A self-service group is an ordinary mesh Group object, the same
kind MeshComposer creates, plus a small set of side tables. There is
no second provisioning path: the export engine, the projection
rules and the export queue do the work exactly as for every other
object.
What makes it self-service is a set of marker attributes the API stamps on the mesh object:
| Marker | Values | Read by |
|---|---|---|
imProvision | true / false | the AD projection rule’s precondition |
imSyncToEntra | true / false | the Entra projection rule’s precondition |
imMembershipAuthoritative | true | both preconditions, and the export projection |
entraGroupKind | Security / Microsoft365 | the Entra connector |
The markers are the lifecycle switch. Deleting a group flips
imProvision and imSyncToEntra to false; the preconditions then
fail and the engine emits a Delete for every target the group is
linked on. imMembershipAuthoritative is what lets a group be
emptied: with it, an edge-less group projects an empty member
value, which is how expiry strips the directory group. Composer
groups do not carry it and are unaffected; imported groups do not
carry it until an administrator onboards
them.
Ownership is managedBy relationship edges (group to person) plus
an owners table holding the full list and its history. The API also
stamps a managedBy attribute holding the primary owner’s mesh
object id, so the projection rule has a source to flow. On AD the
engine swaps it for the owner’s DN (AD models managedBy as one
DN, so co-owners are not represented). On Entra the engine expands
it to every owner, but only when the rule flows a target attribute
named exactly owners.
Membership is member_of edges with source SelfService. Composer
edges carry their own source, and each reconciler only diffs its
own, so the two never disturb each other.
A person, for every purpose here (owner, member, join requester,
the people picker, the members an onboarding carries), is a live mesh
object whose type is User or Person. Connectors project people as
User unless a projection rule renames the type. A mesh that uses
another name lists it in the API’s Groups:PersonObjectTypes
setting (a JSON array, compared case-insensitively); the list replaces
the default, so include User if it is still in play.
Setup
1. Deploy the schema
The installer’s database step creates the group tables and seeds the two projection templates. No policy row is seeded: the documented defaults apply until someone opens the configuration page, so the feature works before it is configured.
Upgrading from a release that already had the group tables: this
release adds an Origin column to IM_Groups (Created or
Adopted). The installer’s database step adds it during the
upgrade. A database updated outside the installer needs
the database step run
before the Admin API starts, or every group call fails with an
invalid column name.
2. Apply the projection templates
Apply the two shipped templates from Connector → Projection → Apply template, against the AD connector and, if you sync to the cloud, the Entra connector. See the projection templates runbook.
| Template | Mesh → target | Precondition |
|---|---|---|
| Self-Service Group Export (AD) | Group → group | imProvision and imMembershipAuthoritative are true |
| Self-Service Group Export (Entra ID) | Group → group | imSyncToEntra and imMembershipAuthoritative are true |
Both preconditions test two markers. imProvision alone would also
select MeshComposer’s create-mode groups, which carry the same
marker. These are deliberately not the older AD Group Export
template, which has no precondition and would export every mesh
group in the estate, imported ones included.
Applying a template creates an independent rule you can edit. Two things to know:
- On the Entra rule, do not rename the
ownerstarget attribute. The engine tests for that literal key to decide whether to run the owner expansion. Rename it and co-owners added in the portal never reach the cloud group. - Set the AD template’s target OU to a real container before you
apply it. It ships as
OU=Groups,DC=contoso,DC=comand is where new groups are created.
2a. Verify the managedBy schema row
The engine only resolves a mesh id to a directory DN for attributes
declared as a single-valued reference for that object type. The
seed adds that row for managedBy on Group, but it never
overwrites a row you already had. Check Schema → Attributes:
| Field | Value |
|---|---|
| Attribute name | managedBy |
| Object type | Group |
| Data type | reference |
| Multi-valued | no |
If the data type reads anything else, change it by hand, or AD
receives the owner’s raw mesh object id instead of a DN. Declaring
it a reference is safe on an existing estate: an imported group
whose managedBy already holds a DN string keeps that value.
2b. Set the AD connector’s delete mode
Set the AD connector’s Delete mode to disable-or-delete (new
in this release) or delete. Under disable a group’s delete
fails loudly and the queue item stays red: a group has no
userAccountControl, so there is nothing to disable, and the
connector refuses rather than reporting a delete it did not
perform. Self-service deletes never reach the directory until the
mode is changed.
3. Grant the Entra app registration its Graph permissions
Group export needs these Application permissions with admin consent, on the app registration the Entra connector already uses:
| Permission | Needed for |
|---|---|
Group.ReadWrite.All | create, patch and delete the group; read and write its owners |
GroupMember.ReadWrite.All | add and remove members |
User.Read.All | resolve mesh persons to Entra user ids (the import already needs this) |
Members and owners are written as Entra object ids, so the Entra user import must already be running and joined to mesh persons. Membership convergence is one Graph call per member added or removed, and the run log warns above 500 changes. Plan on groups of a few hundred members. See the Entra connector runbook.
4. Configure the policy
Configure → Groups writes the single install-wide policy row.
| Setting | Default | Notes |
|---|---|---|
| Creator groups | empty | mesh groups whose members may create; see below |
| Allowed group types | empty | which of Security / Distribution / MailEnabledSecurity / Microsoft365 users may pick |
| Naming regex, name prefix | none | on top of the 20-character sAMAccountName limit |
| Max expiry days | 365 | caps what an owner may set, including on renewal |
| Default renewal period days | 365 | |
| Default target OU by type | none | OU per group type |
| AD connector, Entra connector | none | which connectors receive the exports |
| Mail domain | none | builds mail for mail-enabled types |
| Expiry warning days | 30, 7, 1 | days before expiry that owners are warned |
| Retain expired days | 30 | how long an expired group is restorable |
The two empty lists mean opposite things. An empty creator list
means only groups.admin holders can create. That is the
shipped default and is restrictive on purpose. An empty allowed-type
list means all four types are allowed.
A user may create a group only if they hold groups.own and the
mesh holds a membership edge from one of the creator groups to their
person object.
The policy is one row, replaced whole. Sending the policy over
the API (PUT /api/groups/policies) must include every field; an
omitted field is written as its default. An empty expiry-warning
list is a real value meaning never warn.
5. Configure email
Notifications always write an in-portal inbox row. Email is additional and off until enabled under Settings → Email, where you choose SMTP, Mailgun or Microsoft 365. Configure → Groups shows a link to that page. Installs that already had the SMTP relay set up keep sending, and their settings now appear under Settings → Email with SMTP selected. See the Email runbook.
A recipient’s address is their person object’s mail attribute. No
mail means inbox only, and the notification row records the
reason. A send failure is recorded on the row and never fails the
request that triggered it.
Roles and permissions
| Permission | Admin | Operator | Viewer | User | Grants |
|---|---|---|---|---|---|
groups.read | ✓ | ✓ | ✓ | ✓ | browse joinable groups, own memberships and requests |
groups.request | ✓ | ✓ | ✓ | join, leave, cancel own requests | |
groups.own | ✓ | ✓ | ✓ | create within policy, manage owned groups, decide their requests | |
groups.admin | ✓ | any group, policies, high-impact decisions, restore, delete, override | |||
groups.audit.read | ✓ | ✓ | ✓ | audit query and CSV export | |
groups.notify.read | ✓ | ✓ | ✓ | ✓ | own inbox |
Ownership is a fact, not a role. Every owner endpoint checks the
owners table (or groups.admin). Granting someone groups.own does
not give them any existing group.
A group can be an owner. An owner row may name a mesh group instead
of a person. Every direct member of that group then holds owner
standing: they see the group under My Groups, get its join requests in
their owner queue, and may approve, add, remove, edit and renew exactly
as a named owner would. Membership is read from the mesh the same way
creator groups are (relationship types member / member_of, group →
person, any source), so an imported AD or Entra group works as soon as
its membership has been imported; nested groups are not followed. See
Groups as owners.
Sign-ins are resolved to mesh persons by UPN, mail or
sAMAccountName. An ambiguous match is refused, not guessed.
Workflows
Join policies
| Join policy | A join request does |
|---|---|
Open | adds the member immediately, queues the export, audits MemberAdded |
OwnerApproval | creates a pending request and notifies the owners |
Closed | is refused |
High impact needs two decisions
A group flagged high impact requires a second decision from a
groups.admin holder. After owner approval (or immediately, on an
Open group) the request waits for an administrator. The
membership edge is not written until the admin approves, so an
open high-impact group is not a back door.
The owner decides first, then a different administrator decides. The same person cannot satisfy both arms, and the admin arm is not a shortcut past the owner arm. Denials are exempt: an administrator may deny at any stage. Groups that are not high impact keep the single-administrator override. High impact and group type are admin-only fields.
Separation of duty
The owner deciding a request must not be the person who raised it. A sole owner therefore cannot approve their own join: the group needs a co-owner, or an administrator has to decide. A single-owner group is a dead end for self-approval by design.
Creating a group without a mesh person
“Your sign-in could not be matched to one person in the mesh” on
New group means the signed-in account is not a person object in the
mesh (a demo mesh, or an admin account from a domain the mesh does
not import). A groups.admin holder can still create the group by
naming at least one owner on the form: the first named becomes the
primary owner, the rest co-owners, and the audit actor stays the
administrator. Anyone else needs their account imported first.
Name reservation
A deleted or expired group’s name stays reserved until the retention purge frees it, and the refusal names that date. This mirrors Entra’s hold on a deleted group’s mail nickname. See the arithmetic under Expiry, retention and deletion.
Other actions
- Owner add / remove. Removal is immediate; add is immediate unless the group is high impact. An owner may be a person or a mesh group (below).
- Leave. Always allowed.
- Edit. Display name, description, join policy, renewal period, and target OU (before the group goes active). Turning Entra sync on queues the Entra export. Turning it off does not delete the cloud group; the audit entry and the notification both say so.
- Renew. Extends the expiry by the renewal period, capped by the policy maximum.
Every one of these writes an audit row.
Groups as owners
The owner picker on the New-group form and on Add a co-owner offers
mesh groups as well as people (the API call is
GET /api/groups/people?includeGroups=true; group rows carry
kind: "Group"). Naming a group, for example Helpdesk, means:
- Standing. Every direct member of Helpdesk manages the group in
the portal.
GET /api/groups/melists the caller’s groups, and the owner controls appear when an owner row matches one of them. The API makes the same check, so the portal cannot grant what the API refuses. - Directory authority stays with people. A group owner gets no
managedByedge and is never the primary owner: AD’smanagedByand Entra’sownerskeep naming people. Entra refuses a group as a group owner, so this is what keeps an Entra-synced group exporting. If a group’s only owners are groups,managedByis cleared, as it is for an ownerless group. - Notifications. Owner-bound notices (join requests, expiry warnings, Entra sync switched off) fan out to the group’s direct members, each person once, capped at 100 recipients per owner group with a warning in the API log when the cap is hit.
- Rows and audit. The owner row records the group’s display name as
its username;
GET /api/groups/:id/ownersaddsownerKind(PersonorGroup).OwnerAddedandOwnerRemovedaudit rows carryownerKindtoo. - Rules. A group cannot own itself. Only live people and live mesh groups may own; anything else is refused with 400. The orphaned-owner sweep drops an owner group that has been erased from the mesh, but an owner group that still exists with no members is not detected: such a group is effectively ownerless until someone notices.
Onboarding groups you already have
Everything above describes groups the portal created. Every real
estate is brownfield: the groups people actually want to govern
already exist in Active Directory and arrived in the mesh through an
import. Configure → Groups → Onboard existing brings those groups
under self-service management without recreating them. The group’s
mesh object, its anchor and its connector link are reused; what
onboarding adds is the IM_Groups row (status Active, Origin = Adopted), its owners, a self-service membership edge for every
current member, and the three markers, all written in one save.
From that moment the group behaves like a created one everywhere: Browse and Join, My Groups, Approvals, expiry, renewal, high impact, audit and notifications. The mesh becomes authoritative for its membership. Joins and leaves in the portal reach AD, and a member added directly in AD is reverted the next time the group is exported. Onboard a group only when that is what you want.
What stays the import’s
Onboarding writes only the markers and the owner reference. Name,
description, mail, group type and the anchor stay exactly what the
import brought in, because a second copy of any of them would be
exported beside the first (Finance;Finance). Three consequences:
- Rename and description edits are refused on an adopted group, with the message “This group’s name and description come from the directory import; change them in Active Directory.” My Groups shows an Adopted badge and locks those two fields.
- The naming policy (prefix, pattern) is not applied to adopted groups.
- Group type is a label. Domain-local and builtin groups are
shown as Global in the portal; onboarding never writes
groupType.
How membership is resolved
The source of truth is the group’s own Management Space row on the
AD connector: its member attribute is the list of DNs as AD holds
them now. Each DN is looked up against the user rows imported on the
same connector, and the preview reports one outcome per member:
| Outcome | Meaning | After onboarding |
|---|---|---|
| Carried | A live, linked person row with that DN | stays a member; the mesh now owns the edge |
| Nested group | The DN is a group | removed on first export; membership is flat |
| Not imported | No row: outside the import scope, a foreign security principal, a contact, a computer | removed on first export |
| Unlinked | A row that is not joined to a mesh object | removed on first export |
| Deleted | A soft-deleted row | removed on first export |
“Removed on first export” is a real change to a production
directory. The preview lists every such DN with its reason, the
request must carry an accepted count per group that is at least
the live count, and the confirm dialog makes you type ONBOARD when
any group would lose members. A group whose every member would be
dropped is refused outright: an onboarding that would empty a
populated group is never right. Link the members first, or leave the
group alone.
An empty AD group has no member value at all, so the connector
cannot tell “empty” from “attribute not loaded”. The preview flags
such a group as will be onboarded as an EMPTY group, and it needs
its own explicit acceptance plus the typed confirm. If no group
on the connector carries member, the attribute is missing from the
connector’s load list and onboarding refuses with that reason.
A group with more than 1,500 members is refused: AD returns such memberships in ranges the connector does not retrieve, so the mesh would see a partial list and treat it as the whole.
Refusals
Each group in a batch is decided on its own, so one bad group does not fail the other forty-nine. A group is refused when it:
- is already onboarded, or already managed another way (any marker from any source, or any existing self-service membership edge: Composer groups are refused here, since treating one as self-service would export conflicting markers and delete it);
- is not a mesh
Grouplinked to a live row on an AD connector, or is linked on more than one AD connector; - has a
sAMAccountNamelonger than 20 characters; - would lose members without the accepted count, or would be emptied;
- has no owner named, or an owner that is not a mesh person.
Owners are required because the orphaned-owner sweep would otherwise
close a freshly onboarded group within a minute. The owner reference
(managedBy) is written only when the group has no managedBy from
any source; an imported value is left alone, and the preview says
keeps its AD managedBy. Approvals read the owners table, so owners
work in the portal either way.
Hybrid groups
If the group’s mesh object is also linked to an Entra row with
onPremisesSyncEnabled true, Entra Connect owns the cloud copy. Such
a group shows a Hybrid badge, Entra sync is forced off whatever
the batch setting says, and later attempts to turn it on are refused.
Undo
POST /api/groups/{id}/release (groups.admin, API only in this
release) reverses an onboarding: it removes the IM_Groups row, the
owners, every self-service edge and attribute on the group, the
group’s pending export-queue rows and its export snapshots, and
cancels pending join requests with a notification. AD membership is
not touched; with the marker gone the next export leaves member
alone, exactly as before onboarding. Release is refused for groups
the portal created, which have Delete. A failure part-way through an
onboarding runs the same release automatically and audits
GroupOnboardFailed.
Audit
One hash-chained GroupOnboarded entry per group records the
connector, the carried count, every dropped DN with its reason
(capped at 500), the accepted counts, the owners and the settings.
GroupReleased records the same shape on undo. There are no
per-member events; the member list is the entry.
Known issue: imported groups and Delete if unlinked
The shipped AD group template carries Delete if unlinked so that
deleting a self-service group deletes the directory group. The
engine evaluates that flag per rule for any queued export of a mesh
Group that names no connector, and an imported AD group that
carries none of the markers fails the rule’s precondition, which the
engine currently reads as “no longer eligible, delete”. On an
estate where the AD connector imports groups, an imported group that
is queued that way can be deleted from AD. Until the engine refuses
to delete objects it never provisioned, apply the AD template with
Delete if unlinked off on any connector that also imports groups,
and delete retired self-service groups in AD by hand. The runbook
will say when this restriction is lifted.
Acceptance groups
Run these on the test directory before onboarding anything real:
- A fully carried group changes nothing. Onboard a group whose
members are all imported, linked users. Trigger the export and
compare AD’s
memberbefore and after: identical, and the export confirmation shows no membership delta. - A mixed group drops exactly what the preview said. Onboard a group holding a nested group and a foreign security principal. The preview must list both; the onboarding must refuse without the accepted count; with it, the first export removes exactly those two entries and nothing else.
Expiry, retention and deletion
A group’s life after activation runs on a schedule:
- Warning. At each warning threshold (default 30, 7 and 1 days out) the group is marked pending expiry and its owners are notified, once per threshold.
- Expiry. At the expiry date the group becomes expired, all membership edges are removed, and the resulting export empties the directory group. The object stays and the owners are kept.
- Restore window. For the retain-expired window (default 30 days) an owner can restore the group with a new expiry. Members are not restored; re-adding them is a deliberate act.
- Deletion. After the window the group is deleted: Delete exports go to every linked target and the mesh object is erased. The group row itself stays, holding its name.
- Purge. The group row is removed a further retain-expired window later. This is the step that frees the name.
A name can therefore be reserved for two windows, 60 days at the defaults. A group that expired naturally spends one window reaching deletion and one more reaching purge. A group deleted outright by an administrator waits one window. This is the first thing to check when a creation fails with a duplicate-name error for a group nobody can see.
Sweeps
Three background passes on the API host, configured in the Admin
API’s appsettings.json. Each is disabled by setting its interval
to 0 or less.
| Sweep | Cadence key | Default | Does |
|---|---|---|---|
| Expiry | IdentityMesh:Groups:ExpirySweepHours | 24 | warnings, expiry, deletion and purge after the retain window |
| Orphaned owner | IdentityMesh:Groups:OwnerSweepHours | 24 | drops owners whose person is gone; promotes their manager |
| Provisioning status | IdentityMesh:Groups:StatusSweepMinutes | 1 | marks a pending group active when its AD link appears; records error targets |
The orphaned-owner sweep escalates rather than leaving a group
unowned. When the last owner goes, it resolves that owner’s manager
and makes them the owner, notifying them. With no manager, the group
is flagged as needing an owner, its join policy is forced to
Closed, and every groups.admin holder is notified.
The status sweep is why a new group shows Pending for a minute or two. If the export drain is not running it shows Pending forever: a paused engine looks identical to a slow directory from the portal. Check the export queue before assuming the group failed. Consider a status cadence of 5 minutes on a first rollout rather than the default 1; the sweep queries every non-active group each pass.
Provisioning-error notices are throttled to one per connector per group per 24 hours. The queue item is the live signal; the notification is the prompt to go and look.
Notifications
Each notification is written to the recipient’s in-portal inbox (the bell in the navbar), then attempted as email if email is set up under Settings → Email. The delivery outcome is recorded on the row.
Inbox rows are purged after IdentityMesh:Retention:NotificationsDays
in the Sync Engine’s appsettings.json, default 90 days, 0 or
negative to disable. Every row past the window goes, read or
unread. The inbox is not evidence; the audit trail is the group
audit table below. Expiry warnings fan out to every owner at three
thresholds, so this is the fastest-growing table the feature adds.
There is no UI for this setting.
Audit and its retention
Every state change writes one hash-chained row to the group audit
table, stamped by the same chain the admin and vault audit use.
Query and export it from Groups → Group Audit, or at
GET /api/groups/audit and …/audit/export.csv, both gated on
groups.audit.read. Filters: group, user, from, to.
The CSV cannot report a failure that happens after streaming began. A read that fails part-way through produces a truncated file under a success status. Check the last line of any export you intend to keep as evidence, and fetch it again if it stops mid-row.
Group audit is purged under the same window as the rest of the
audit evidence, Retention.AuditDays (default 30 days, 0 or
negative to keep forever). Purging removes the oldest rows, so the
surviving chain stays verifiable; a full-history verification on a
purged deployment reports exactly one broken link at the retention
boundary, and that is expected. See the
audit retention runbook.
Known standoffs
These look like faults and are not. Each is a deliberate refusal to record a convergence that did not happen.
- The last owner in Entra. Entra refuses to remove a Microsoft 365 group’s last owner. When the mesh asks for an owner set that would empty the cloud group’s owners, the connector skips the removal and reports the export as failed, every drain, until the group is given another owner. Assign an owner; do not clear the queue item.
- An ownerless group keeps its last cloud owner. A group flagged as needing an owner is never exported to Entra with an empty owner set. Entra keeps whichever owner it last had until someone is assigned in the mesh.
- Membership and ownership authority is by presence. When
memberorownersis present in the outgoing change it is authoritative; when absent, that dimension is left alone. Absence is not emptiness, which is what protects every imported group. Only user members are ever removed from an Entra group; nested groups and service principals are left alone, with a warning. - Create is idempotent, adoption is narrow. A retried create looks the group up by mail nickname and adopts it only if the display name matches, the group is not directory-synced, and IdentityMesh made it. Any other match is refused with the reason.
- Mail-enabled types are AD-mastered. Only Security and Microsoft 365 groups are created in Entra. Mail-enabled security and distribution groups reach the cloud through Entra Connect, and the portal shows them as in Entra via directory sync.
Troubleshooting
The people picker finds nobody
Searching for a known account on the New group owners field, the
co-owner picker or the members picker returns nothing, and
onboarding previews report every member dropped. The search only
looks at mesh objects of the person types (User and Person by
default), matched on the anchor, displayName, userPrincipalName,
mail, sAMAccountName, accountName (the metaverse name the
shipped templates use) and whatever Vault:RequesterMatchAttributes
lists. Check the object type your projection rules produce on the
Mesh Objects page; if it is something else, set
Groups:PersonObjectTypes. If the sign-in lives in an attribute with
another name, add that name to Vault:RequesterMatchAttributes, which
makes it both searchable and the name the group pages show. Earlier
releases only recognised Person and did not search
accountName; on a template-shaped mesh only the anchor matched.
Ownership is not being managed
Work these in order; the first two are configuration, the rest are data.
- The rule does not flow
owners(Entra) ormanagedBy(AD). The shipped templates have it; a hand-built or edited rule may not. On Entra the target attribute must be spelled exactlyowners. managedByis not declared as a single-valued reference (AD only). The symptom is a GUID in AD’smanagedBy, not an empty one. See step 2a.- The group has no owners. The portal shows the status; assign an owner.
- The owners exist but are not provisioned on that connector. The engine drops the key and defers the export. If they are merely late it clears itself; if their target object was deleted it never clears (see below).
- Entra refuses to remove the last owner. The export fails every cycle rather than succeeding with no owners.
The export queue never empties, and nothing is failing
A group can sit in the queue indefinitely with no failed items. The
queue item’s reason ReferenceDeferred is this case: a member,
owner or managedBy reference could not be resolved to that
person’s identifier on the target, so the engine wrote what it
could and re-queued the rest. The Sync Engine log (not the
per-connector run log) records how many references did not resolve.
A late member resolves on its own. A member whose target object was deleted never does, and the same group reappears on every drain. Either remove the member from the group, or re-provision their target object. Deleting the group also ends it.
Group membership shrank after an import
Narrowing an AD connector’s OU or filter marks the excluded
population deleted, and every group containing those people is
re-exported with a shortened membership. After narrowing scope,
run a full import and read the drift queue before you let exports
drain. When more than Export:MaxDeletedMemberFraction of a
group’s members (a system setting, default 0.5) resolve only to
deleted rows, the export omits member entirely and defers instead
of stripping the group. A warning names the group and the counts.
Exports for one connector type stop, with nothing failing
IdentityMesh:Export:PerExportTimeoutSeconds (new in this release,
default 120, 0 disables) bounds one queue item’s initialize plus
export. On expiry the item fails and the message names which
phase ran out: during initialize means the directory would not
let the connector bind; during export means the bind worked and
the write did not. Raise it for a slow target; do not disable it on
a connector that has ever hung.
Nothing exports at all
Check the markers before the rule. Both preconditions require
imMembershipAuthoritative in addition to imProvision or
imSyncToEntra, and a precondition that evaluates false, or fails
to parse, is treated as “do not project” with no error surfaced.
Confirm all the markers are present on the mesh object.
Acceptance round trips
Run these in order on a test directory and tenant before opening the feature to users.
- Create reaches both directories. Create a Security group with
Entra sync on. Expect the AD group within five minutes and the
Entra group within one cycle, the portal flipping to Active, and
managedByin AD holding a DN, not a GUID. - Approved join reaches AD, with audit. With owner approval, a
different user requests to join; the owner approves. Expect the
member in AD (and Entra if synced) and the audit chain
RequestSubmitted,RequestApproved,MemberAdded, matched by the CSV export. - Delete leaves both directories. Delete the group as an administrator. Expect both directory groups gone, the Management Space rows marked deleted, a single Delete in the queue, and a same-name create refused with the date retention frees the name.
Record the actual times and any Graph error text verbatim. Then run the two onboarding acceptance groups before onboarding a real one.
Related
- Audit retention — the sweep that purges the group audit table and the notification inbox.
- Projection templates — how the two shipped group templates are applied and edited.
- Entra ID connector — Graph permissions and how group export converges owners and members.
- Self-service groups feature overview.