Group synchronisation is easy to build in the direction that adds. Somebody joins the engineering group, they gain the engineering role, everybody is pleased. The reverse direction is where products differ from each other, and where most of them never made an explicit decision.
Removal from a group can mean four different things, and a directory event does not tell you which one the customer intends. Losing a permission. Losing access to specific objects. Losing a seat. Or ceasing to exist. Picking one silently is how a sync ends up deleting something an administrator did not expect.
Separate the grant from the consequence
The safe model is that group membership grants permissions and nothing else. Removing the membership removes the permissions, immediately and completely. It does not remove the person, their content, their comments or their history, because none of those were granted by the group.
That distinction sounds obvious written down and is easy to lose in code, because the convenient implementation cascades. A foreign key with a delete cascade from membership to created objects will make removal from a group destroy work, and the person who clicked the button in their directory had no idea that was on the table.
- Group removal revokes permissions; it does not delete the person
- Objects survive their creator's membership — reassign ownership rather than cascading
- Existing sessions must lose the permission on the next request, not at expiry
- Tokens and API keys derived from the role are revoked in the same operation
Removing somebody from a group should revoke what the group granted, and nothing that it did not.
The empty group problem
Providers do not always send removals as removals. Some send an authoritative membership list on every change, and if that list arrives truncated — a paged response where the second page failed, a filter that matched nothing during a directory migration — a naive handler reads it as everybody left and revokes access for the whole company at once.
Guard against the shape rather than the cause. A membership update that empties a non-empty group, or removes more than a threshold share of it in one operation, is worth pausing on: apply it, but require confirmation, or hold it briefly and re-fetch to confirm the directory really says that. The rare false alarm is much cheaper than the outage.
Make it visible before it takes effect
The administrators who trust a directory integration are the ones who can see what it is about to do. A pending-changes view listing who is about to lose what, with the option to apply now, is more valuable than any amount of documentation about your sync behaviour.
And record it afterwards. Every permission change caused by a directory event belongs in the audit trail with the group, the event and the resulting difference, because the first question after an unexpected loss of access is always what changed and who changed it — and the honest answer, that their own directory did, is only convincing with the record attached.
Everything here, already built
Sign-in, enterprise SSO, directory provisioning, roles and an audit trail behind one API. Start with the quickstart and have a working sign-in this afternoon.