SfSkills Domains Docs GitHub

Home / admin / chatter-group-governance

chatter-group-governance

Use when admins are governing the Chatter group lifecycle — creation policy, public/private/unlisted visibility decisions, group ownership transfer when owners leave, archived vs inactive vs deleted state changes, auto-archive behavior, naming conventions, group templates (Information Templates), and orphan-group cleanup after user terminations.

Open the skill folder on GitHub


Chatter Group Governance

Activate this skill when an admin needs to design or repair Chatter group lifecycle controls — naming, visibility, ownership, archival, and cleanup. The skill is about governance of the group population, not about feed noise inside a single group (use admin/chatter-notification-tuning for that).


Before Starting

Gather this context before proposing changes:


Questions to Ask Before Configuring

Ask these before touching Setup or writing a cleanup script. Each one maps to a gotcha that turns a tidy-looking cleanup into an irreversible one.

AskWhy it mattersWhat a good answer adds
"Who in this org holds Manage Unlisted Groups, and can they name themselves?"View All Data and Modify All Data do not reach unlisted groups (L67109–67115), so an "all groups" report run by a system admin is silently incompleteEither a named compliance holder, or the decision to set unlistedGroupsEnabled to false
"Is allowChatterGroupArchiving on, and has anyone turned it off to stop surprise archiving?"That flag covers manual archiving too (api_meta.txt L112476–112480); with it off, delete is the only lever and delete cascades to files shared elsewhereThe right fix — per-group IsAutoArchiveDisabled — instead of an org-wide switch
"For the groups you want to keep alive, is anyone posting, or only reading?"The archive clock runs on LastFeedModifiedDate, the last post or comment (L67298–67314); reads never advance itThe exemption list to set IsAutoArchiveDisabled = true on, before the next sweep
"Do any of these groups hold files that are also shared somewhere else?"Deleting a group "removes the files from other locations where they were shared" (L67402–67404)The archive-vs-delete split, decided on evidence rather than on inactivity alone
"Who is the transfer target, and are they a person or a service account?"Only the owner or a Modify All Data holder can repoint OwnerId (L67378–67379); a person-owner re-orphans on their next departureA steward account for ownership plus a named human manager for moderation
"Is this cleanup happening alongside a batch user deactivation?"Deactivating multiple users at once hard-deletes the EntitySubscription rows between them, unrecoverable on reactivation (L111169–111174)A sequencing decision, and an EntitySubscription export taken before the wave
"Are guests (CanHaveGuests) already true on any group in scope?"That flag "cannot be set back to false" once true (apexrefguide.txt L111947–111948)An honest exit plan — remove guests and archive — instead of a promise to close the group later

What a proper configuration adds over just archiving the dead groups: the org keeps a discoverable, auditable group population — every active group has a reachable owner, every exemption from the archive sweep is a deliberate per-group flag rather than an org-wide switch, unlisted groups are either governed by a named permission holder or turned off, and the settings baseline lives in source control so the next org inherits the same policy instead of rediscovering it.


Core Concepts

Concept 1 — Three group types, three sharing models

CollaborationGroup.CollaborationType is a picklist with three values that drive visibility very differently:

TypeDiscoverable in group listPosts visible toMembership requires approval
PublicYesAll internal users (and Customer Community users with feed access if so configured)No — anyone can join
PrivateYes (name + description visible, posts not)Members onlyYes — owner / manager approves
UnlistedNo — and not to View All Data / Modify All Data holders either; only Manage Unlisted Groups reaches itMembers and Manage Unlisted Groups holdersInvitation only

Two consequences admins miss:

Concept 2 — Archived ≠ Inactive ≠ Deleted

Three distinct lifecycle states. Confusing them is the most common admin error:

There is no "Inactive" state in metadata — the term is colloquial for "Archived but not yet Deleted." Decide explicitly: archive (preserve audit trail, hide from active lists) or delete (purge permanently).

Concept 3 — Group ownership and the deactivated-owner problem

CollaborationGroup.OwnerId is a hard reference to a User record. Two non-obvious behaviors:

  1. Deactivating the owner does NOT reassign the group. The user is set IsActive = false. The group's OwnerId still points at them. The group continues to function — members can post, the group can be modified by other group managers — but the owner-only operations (deleting the group, transferring it, changing its type) are now stuck unless a system admin intervenes.
  2. Only the current owner or a Modify All Data holder can transfer ownership — "Only the current group owner or people with the Modify All Data permission can update the OwnerId" (L67378–67379). Not "an admin" loosely: that specific permission. The member-side note says the same thing from the other direction — "To change the group owner, use the OwnerId field on the CollaborationGroup object" (L67477–67478) — so promoting someone to group manager is explicitly not a transfer.

The governance pattern: every group should have a backup manager (a CollaborationGroupMember with CollaborationRole = 'Admin' — "Managers can post and comment, change member roles, edit group settings, add and remove members, delete posts and comments, and edit the group information field", L67473–67476). The backup manager covers moderation but cannot transfer ownership; a Modify All Data holder must do that. So the offboarding workflow is:

Doing it in the other order leaves orphaned-owner groups that require manual cleanup later.

Concept 4 — Group templates (Information Templates) and naming conventions

Salesforce ships Group Information Templates — admin-configured Markdown-style templates that prefill the group's "Information" tab on creation. Two practical uses:

Templates do not enforce anything — a determined user can ignore them. But combined with restricting group creation to a permission set (so only "trained" users can create groups at all), they cut sprawl materially.

A common structural naming convention for orgs of any size:

<Type>-<Scope>-<Purpose>

Examples:
  Project-AcmeMigration-CoreTeam        ← a project workstream
  Team-Sales-EnterpriseAEs              ← a standing team
  Topic-Salesforce-ReleaseTrack          ← an interest / topic group
  Announce-AllHands                      ← broadcast group
  Customer-AcmeCorp-AccountTeam         ← a customer-specific group

Prefixes like Project-, Team-, Topic-, Announce-, Customer- make bulk operations (archive all Project-* groups closed last quarter) trivial via SOQL WHERE Name LIKE 'Project-%'.


  1. Retrieve the metadata baseline and lint it. sf project retrieve start --metadata Settings:Chatter,PermissionSet,Profile, then run the bundled checker:
    python3 scripts/check_chatter_group_governance.py --manifest-dir force-app/main/default

    Two findings stop everything else: CGG-UNLISTED-UNGOV (unlisted groups are on and nobody holds Manage Unlisted Groups, so your inventory in step 2 will be incomplete) and CGG-ARCHIVE-OFF (archiving is disabled org-wide, so the archive branch of step 4 does not exist yet). references/metadata-examples.md sections 1–2 carry the deployable Chatter.settings and PermissionSet shapes for whatever you have to change.

  2. Export the group population and lint that too. Groups are data, not metadata — the export query

    is in references/metadata-examples.md section 3. Run it as a user who holds Manage Unlisted Groups if step 1 says one exists, then:

    python3 scripts/check_chatter_group_governance.py \
        --manifest-dir force-app/main/default \
        --group-inventory groups.csv \
        --name-prefixes Project- Team- Topic- Announce- Customer- \
        --inactive-days 365

    CGG-INV-ORPHAN is the ownership-transfer queue, CGG-INV-STALE the archive queue, CGG-INV-EMPTY the delete candidates, CGG-INV-NAMING the convention debt. Record the counts — they are the baseline you re-measure against in step 7.

  3. Decide creation policy, and write it as metadata. Move Create and Own New Chatter Groups off

    profiles and onto a named Chatter_Group_Creator permission set; add Unlisted_Group_Auditor if the org keeps unlisted groups. Both shapes are in references/metadata-examples.md section 2 — read the UNVERIFIED note there about the permission API names before you deploy them.

  4. Reassign every orphaned owner, before you archive anything. Use the manager-first script in

    references/metadata-examples.md section 4: it prefers an active group manager and falls back to a steward service account, in three queries and one partial-success DML. Archiving a group whose owner is already gone just hides the problem — gotchas 2 and 3.

  5. Split stale from empty, then archive or delete. Archive (IsArchived = true) anything with

    substantive history; delete only groups the checker flagged CGG-INV-EMPTY and whose direct CollaborationGroupMember count you confirmed — MemberCount is a nillable rollup, gotcha 9. Before any delete, check the group's files: the delete cascade removes them from every other location they were shared into, gotcha 7. Standing groups that should never auto-archive get IsAutoArchiveDisabled = true instead (section 5 of the metadata examples), not an org-wide setting change.

  6. Wire the offboarding hook and sequence it. Ownership transfer runs before User.IsActive flips.

    Read references/llm-anti-patterns.md anti-pattern 2 first — the obvious record-triggered Flow is the wrong shape here. And if this is a deactivation wave, read gotcha 11: deactivating several users at once hard-deletes the follow relationships between them, with no restore on reactivation.

  7. Re-measure quarterly and diff the counts. Re-run both checker invocations from steps 1–2.

    CGG-INV-ORPHAN should trend to zero, CGG-INV-NAMING should fall as the permission set narrows who creates groups, and a rising archived-to-active ratio is health, not decay. Commit the Chatter.settings and permission-set files so the policy travels with the org.


Reference Files

FileRead it when
references/metadata-examples.mdWriting the deployable Chatter.settings and PermissionSet XML, the package.xml and sf project commands, or any of the data-side artefacts — inventory SOQL, ownership-transfer Apex and CSV, archive/unarchive updates, orphan and empty-group detection
references/gotchas.mdThe cleanup ran and something is irreversible, invisible, or missing — unlisted groups absent from an audit, files vanished from unrelated records, a manager who cannot take over a group, a name collision on a bulk load
references/examples.mdWorking a scenario end to end before any XML exists — inventory, creation lockdown, bulk reassignment, the archive-vs-delete call, auto-archive tuning, and the Group Information Template
references/well-architected.mdJustifying open creation vs permission-set restriction, archive vs delete, or person-owner vs steward-owner — and locating the official source behind a claim in this skill
references/llm-anti-patterns.mdReviewing output an AI assistant produced here, especially "just delete the dormant groups" or an offboarding Flow that deactivates and reassigns in one transaction
templates/chatter-group-governance-template.mdRunning workflow steps 1–2 — the inventory, policy, and disposition worksheet
scripts/check_chatter_group_governance.pyWorkflow steps 1, 2, and 7 — before any settings deploy and before any bulk archive or delete

Package files