Features

Audit Log

Vextro automatically logs admin actions to the adminAuditLog table. Document mutations, access control changes, bulk operations, and template management all generate audit entries without configuration.

Logged actions

Document CRUD

ActionWhen
document.createA document is created
document.updateA document is updated (only if fields changed)
document.deleteA document is deleted
document.duplicateA document is duplicated
global.updateA global document is updated

Access control

ActionWhen
access.user.status_changedA user's status is changed (active/inactive/pending)
access.role.createdA new role is created
access.role.deletedA role is deleted
access.role.assignedA role is assigned to a user
access.role.removedA role is removed from a user
access.permission.grantedA permission is added to a role
access.permission.revokedA permission is removed from a role
access.scope.assignedA scope is assigned to a user
access.scope.removedA scope is removed from a user

Bulk operations

ActionWhen
bulk.statusBulk status update
bulk.deleteBulk delete
bulk.tagsBulk tag update
bulk.importBulk document import

Templates

ActionWhen
template.createA template is created
template.updateA template is updated
template.deleteA template is deleted

Entry shape

Each audit log entry has the following shape:

FieldTypeDescription
actionstringDot-delimited action identifier
collectionSlugstring?The collection this event relates to
documentIdstring?The document or user ID this event relates to
userIdstring?The acting user's ID
userEmailstring?The acting user's email
userNamestring?The acting user's display name
detailsobject?Action-specific metadata (e.g. changed fields, previous status)
createdAtnumberTimestamp of the event

Custom audit logging

Use the logAuditEntry utility to write audit entries from custom Convex mutations:

import { logAuditEntry } from "vextro/convex/audit";

export const archiveProject = mutation({
  args: { projectId: v.id("projects") },
  handler: async (ctx, args) => {
    await ctx.db.patch(args.projectId, { status: "archived" });

    await logAuditEntry(ctx, components, {
      action: "project.archived",
      collectionSlug: "projects",
      documentId: args.projectId,
      userId: "user123",
      details: { reason: "quarterly cleanup" },
    });
  },
});

The utility is also re-exported from vextro/convex/admin:

import { logAuditEntry } from "vextro/convex/admin";

logAuditEntry is fire-and-forget. If the underlying write fails, the error is silently swallowed so that audit logging never blocks the primary mutation.

Viewing the audit log

The audit log is available in the admin UI at /settings/audit-log. It supports filtering by action, collection, user, and date range.

Programmatically, use the listAuditLog and getDocumentAuditLog queries generated by the admin module to read audit entries.

Previous
Hooks