Expire dormant users
- Type
- auto_expire_dormant_users
- Category
- Lifecycle
- Enforced atWhen this policy is checked: while someone tries to open, while they create or change an invitation or hold, on a membership change or background sweep (lifecycle), or after a denial (record only).
- Lifecycle
- TiersWhere an admin can set this policy: the whole organization, one integration, or the physical device when the connector supports a device steward.
- OrgIntegration
- EnforcementEnforcement modes this type accepts. Enforce applies the row. Require approval (user sharing only) opens an admin approval inbox instead of blocking.
- Enforce
- DefaultWhat happens when no row of this type is configured.
- Not configured — idle members and residents are not auto-expired.
A background sweep (about every 15 seconds) checks every resident and invitation author in an organization with an enabled row. Idle time is since the person’s last access in the organization, or since their oldest residency or authored invitation if they have never accessed. Matching users have their invitations revoked and residencies removed; the user record remains. Integration-tier rows count only for people who hold a residency or an authored invitation on that integration. Each expiry is audited as policy.dormant.expired. The sweep classifies each person as admin or member, so `applies_to` must name member (or all) to bind non-admins; resident never matches here.
When it is enforced
Evaluated when membership changes or on a background sweep, not on a request the affected person makes. It acts on existing access (for example revoking invitations) or records an audit event; it never blocks an open or an authoring request.
Where to set it
Settings → Policies (org) or the integration Policies tab.
Policies never grant access. See thepolicies architecture guidefor how org, integration, and device tiers combine.
Arguments
The config object on create/update. Row fields outsideconfig are enforcement (this type acceptsenforce; any other value is rejected with 400), enabled (disabled rows never apply), and capability.
| Name | Type | Required | Values | Description |
|---|---|---|---|---|
| days | integer | Yes | — | Idle days before expiry. Integer from 1 through 365. |
| applies_to | string[] | No | adminmemberresidentall | Principal kinds this row binds, as a non-empty array of admin, member, resident, all. Other kinds, a bare string, and empty arrays are rejected. `all` matches every kind this policy can bind. A caller is every kind it is at once, and a row binds when any of them is listed. When omitted, the default applies. Default: Members and residents; admins are not expired unless applies_to names admin. |
How overlapping rows combine
Most-restrictive: minimum of days across applicable rows. Disabled rows never expire. Reject invalid days, do not clamp.
Example
A resident who has not accessed in 90 days loses residencies and authored invitations. Their login still exists. An org admin is left alone unless applies_to includes admin.
{ "days": 90}Integrations
This type is documented on these connectors:
- Home Assistant (home_assistant)
- KNX (knx)
- MQTT (mqtt)
- PalGate Cloud (palgate_cloud)
- Shelly Cloud (shelly_cloud)
- Shelly Websocket (shelly_websocket)
- Tasmota (tasmota)
- Virtual Access (virtual_access)
- Virtual Demo Devices (virtual_demo)
- Waveshare (waveshare)
Related
- Policy catalog
- Policies architecture guide
- Revoke invites on move-out (auto_revoke_on_moveout)
- Notify on new sharing (notify_on_new_sharing)