Skip to content

Audit trails

GCM keeps three separate audit trails so you can answer "who changed this?" without trawling through database backups. Each one lives in a different place because each one is asking a different question.

Data & Logs page with audit + imports tabs

The three logs

LogLives atAnswers
Organization audit log/activity-log and Data & Logs → Audit LogWho in your org created, edited, or deleted a member, donation, group, ministry, school, attendance, or org unit?
Member activity logA tab on every member's profileWhat's happened to this person — joined a group, attended a meeting, received a workflow message, marked lost, recovered?
Import historyData & Logs → Import HistoryDid the CSV import I ran last week finish, and how many rows failed?

There's also a fourth log — the platform audit log — but it's reserved for Genius Church Manager platform admins (us) and tracks cross-tenant impersonation, plan changes, and superadmin role moves. You won't see it from inside your org.

Who can see audit data

PermissionCan see
users.manageThe full /activity-log page across all entity types and actors
config.manageThe Audit Log tab inside Data & Logs (same data, abbreviated view)
Any member's profile viewerThat member's own activity timeline
None of the aboveNothing — audit entries don't leak through other screens

The activity log is permission-gated to users.manage on purpose: most staff don't need to see every teammate's edits, and exposing that data by default invites uncomfortable HR conversations.

What gets logged automatically

A generic audit_log_writes() Postgres trigger watches eight entity tables and writes one row to org_audit_log per material change:

  • members
  • attendances
  • donations
  • groups
  • ministries
  • org_units
  • schools
  • school_enrolments

Material change means: an INSERT, an UPDATE that touches at least one non-system column, or a soft delete (deleted_at set). Bulk updates from imports, workflow actions, and the API all flow through the same trigger — there is no way to write to those tables and bypass the log.

The trigger captures:

  • Actor — the authenticated user's UUID and email (or system for cron/webhook writes)
  • Actioncreated, updated, deleted, restored, plus domain-specific verbs like merge_members
  • Entity — type + ID, so the activity-log row can link directly to the affected member or group
  • Metadata — for updates, the list of changed columns (useful for "what did you change?" but not the before/after values)

Member-specific events (joined a group, marked lost, received a workflow message) are written to a second table, member_activity_log, by application code rather than a trigger — that's the timeline you see on the member profile.

What is not logged

Two deliberate omissions:

  1. Read access. Looking at a member doesn't write a row. If you need view-tracking for compliance, talk to us about the enterprise add-on.
  2. Before/after column values. Storing them would multiply log size by 10-50x. The "changed" array tells you which columns moved, not what they moved from and to. If you need point-in-time member state, use database backups instead.

Retention

Audit rows are kept indefinitely on paid plans and pruned to the last 90 days on Starter. You can export the log before it ages out if you need long-term records — and you should, for any year you sent tax statements.

Where to go next

TIP

If you're investigating a specific change (a donation amount that looks wrong, a missing member), start at the organization audit log and filter by the entity. It's faster than scrolling the member's timeline.