Change Logs

Change Logs establish who changed what in your account configuration, and when. They are the primary stream for compliance audits, security reviews, and investigating configuration changes: each entry records the operation, the subject that performed it, and the full state of the object before and after.

Entries are derived from the database's logical replication stream, which means every committed write to account configuration produces one. Whether a change is made through the admin portal, the REST API, or an automated process such as directory sync, it is recorded through the same mechanism.

Log IDs and ordering

Change Log IDs start with c, and they have a property no other stream has: they always increase. The bits after the stream character encode a microsecond timestamp taken from a single authoritative database clock, followed by a per-account counter that breaks ties. This means that:

  • Sorting entries by log_id reproduces the exact order in which changes were committed, and because the hex encoding preserves byte order, a simple string sort is enough. This makes log_id a reliable foundation for reconstructing the history of an object.
  • A log_id you've already seen acts as a high-water mark, because any new change is guaranteed to sort after it.

The other three streams use random IDs with no ordering meaning, so strict ordering is unique to Change Logs.

Fields

FieldDescription
log_idUnique, always-increasing ID of the entry.
timestampWhen the change was committed.
objectThe table the change occurred on, for example policies or resources.
operationOne of insert, update, or delete.
beforeThe state of the object before the change. Not present for insert.
afterThe state of the object after the change. Not present for delete.
subjectWho performed the change, described below. null for system-initiated changes.

How the subject is tracked

When a change is made on behalf of an authenticated subject, such as an admin in the portal or an API client, Firezone writes a snapshot of that subject inside the same database transaction as the change itself. The replication consumer then attaches it to every Change Log entry that transaction produced. Attribution can never drift from the change it describes, because the two are committed together or not at all.

The subject contains:

KeyDescription
actor_idID of the actor that made the change.
actor_nameDisplay name of the actor.
actor_emailEmail of the actor.
actor_typeaccount_admin_user, account_user, api_client, or service_account.
auth_provider_idThe authentication provider used to sign in. null for API tokens.
ipSource IP address of the request.
ip_regionISO 3166 country code resolved from the IP.
ip_cityCity resolved from the IP.
ip_lat, ip_lonCoordinates resolved from the IP.
user_agentUser agent of the browser or API client.

The location fields are resolved from the source IP using MaxMind's GeoLite2 City database when the entry is recorded, and the portal renders them as a location map in the entry's detail panel.

Changes made by Firezone itself, such as directory sync and retention cleanup, have no authenticated subject, so their subject is null. The LogsChange Logs view hides these system updates by default, and you can enable Show system updates to include them.

Tracked objects

Change Logs cover all account-scoped configuration, including:

  • Account settings
  • Actors, external identities, groups, and memberships
  • Authentication providers: email OTP, Google, Entra ID, Okta, and universal OIDC
  • Directories: Google Workspace, Entra ID, and Okta
  • Devices and static device pools
  • API, Client, and Gateway tokens, and one-time passcodes
  • Sites, Resources, and Policies
  • Trust anchors and trust anchor certificates
  • Log Sinks

Redaction

Sensitive fields such as token secrets and credentials are replaced with [redacted] in before and after before the entry is recorded. The audit trail stays complete without becoming a secondary store of secrets.

Example

A policy update made by an admin in the portal:

{
  "type": "change",
  "log_id": "c0654d20aa1b4a0000000002",
  "timestamp": "2026-07-14T09:26:31.114213Z",
  "object": "policies",
  "operation": "update",
  "before": {
    "id": "0a83588e-0d92-4a4e-a856-4b8f2f4a2f8e",
    "description": "Engineering → GitLab",
    "group_id": "8f3b62d1-4b17-4f5e-9f9d-2c93a1c2b845",
    "resource_id": "5c8f6f6e-7c1a-4d8b-9c9e-1c2c3d4e5f60",
    "disabled_at": null
  },
  "after": {
    "id": "0a83588e-0d92-4a4e-a856-4b8f2f4a2f8e",
    "description": "Engineering → GitLab (MFA required)",
    "group_id": "8f3b62d1-4b17-4f5e-9f9d-2c93a1c2b845",
    "resource_id": "5c8f6f6e-7c1a-4d8b-9c9e-1c2c3d4e5f60",
    "disabled_at": null
  },
  "subject": {
    "actor_id": "e2f6a9c4-30dd-42f7-9f3e-0f8a5f2b7c11",
    "actor_name": "Jamie Admin",
    "actor_email": "jamie@company.com",
    "actor_type": "account_admin_user",
    "auth_provider_id": "9d0c2f4e-8b6a-4c2d-8e1f-3a5b7c9d0e2f",
    "ip": "203.0.113.44",
    "ip_region": "US",
    "ip_city": "San Francisco",
    "ip_lat": 37.7749,
    "ip_lon": -122.4194,
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ..."
  }
}

Viewing and retention

Change Logs live under LogsChange Logs in the admin portal, where you get a JSON diff of before and after plus the subject's location on a map. You can also query them via the REST API's /logs endpoint with type=change. Entries are kept for 90 days.


Need help? See all support options.

Found a problem with this page? Open an issue
Last updated: July 20, 2026