Structured audit trail for compliance. Every action, every context.
Every admin action, every role change, every session event — logged automatically with who, what, when, and why. Compliance-ready from npm install.
The vibe_app.audit_log table stores every auditable event as a structured record: actor (who did it), action (what happened), target_user (who was affected), timestamp, and a JSONB details column for rich context.
Admin actions performed through the dashboard or API routes are logged automatically. You don't call a log function — the middleware and API handlers emit audit events as a side effect of the action.
The admin dashboard renders the audit log as a searchable, filterable feed. Filter by action type, actor, target user, or date range. Export for compliance reviews.
Custom audit events can be emitted from your own API routes using the audit helper — for app-specific actions like "order approved" or "document signed."
Out of the box, every one of these events generates an audit record: - User created / updated / deactivated - Role assigned / revoked (with previous and new role sets) - Session created / revoked / expired - Password changed / reset requested - 2FA enabled / disabled / used - Admin login / logout - App settings changed (with before/after values) - Page permissions modified Each record includes the actor's identity, IP address, and user agent. The JSONB details column captures action-specific context that makes the record useful for forensic review.
A single PostgreSQL table in the vibe_app schema. JSONB details column lets each event type carry its own context without schema migrations. Indexed on actor, action, target_user, and timestamp for fast querying.
-- vibe_app.audit_log schema
CREATE TABLE vibe_app.audit_log (
id SERIAL PRIMARY KEY,
actor TEXT NOT NULL, -- who did it
action TEXT NOT NULL, -- what happened
target_user TEXT, -- who was affected
details JSONB DEFAULT '{}', -- rich context
ip_address TEXT, -- actor's IP
user_agent TEXT, -- actor's browser/device
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Example query: all role changes in the last 7 days
SELECT * FROM vibe_app.audit_log
WHERE action LIKE 'role.%'
AND created_at > NOW() - INTERVAL '7 days'
ORDER BY created_at DESC;For your app-specific actions, emit audit events using the same helper the framework uses internally. Your events appear in the same audit feed, with the same structure, searchable and exportable alongside system events.
import { emitAuditEvent } from '@payez/next-mvp';
// In your API route handler
export async function POST(req: Request) {
const session = await getSession();
const { orderId, amount } = await req.json();
// ... process the order ...
await emitAuditEvent({
actor: session.email,
action: 'order.approved',
target_user: order.customerEmail,
details: {
orderId,
amount,
currency: 'usd',
approvalLevel: 'manager'
}
});
return Response.json({ success: true });
}The audit log is designed to answer questions that auditors and compliance officers ask: - "Who had admin access on March 1st?" — query role.assigned/role.revoked events - "When was this user's account deactivated?" — query user.deactivated events - "Who changed the payment settings?" — query settings.updated events with details - "Show me all failed login attempts this week" — query auth.failed events The JSONB details column means you never need a schema migration to capture new context. Add fields to details as your compliance requirements evolve.
Audit records are append-only — they cannot be modified or deleted through the admin UI. This is by design for compliance. For long-term retention, records can be exported as JSON or CSV from the admin dashboard. For automated compliance pipelines, query the audit_log table directly via the Vibe API.
Audit Logging ships with every @payez/next-mvp install. 10K MAU free. No credit card required.