NIN Connect Docs
Platform (Self-Host)Security

Audit Logging

Security event audit trail for accountability, forensics, and compliance.

Overview

NIN Connect records security-relevant events in the auditLogs database table. Every log entry captures who performed an action, what they did, and contextual metadata like IP address and user agent.

Audit logs are fire-and-forget. They never block request processing and never cause a route handler to fail if the log write encounters an error. This ensures audit logging is invisible to end-users while still capturing events reliably.

Schema

ColumnTypeDescription
idUUIDAuto-generated primary key
actionstringEvent name (e.g. api_key.created)
actorstringDeveloper ID or system identifier
targetstring (nullable)Resource affected (key ID, plugin ID, etc.)
metadataJSON (nullable)Additional context (IP, user agent, request details)
createdAttimestampWhen the event occurred

Logged Events

EventActionActorTargetWhen
Developer logindeveloper.loginDeveloper IDFirebase auth sync
API key createdapi_key.createdDeveloper IDKey IDDashboard key creation
API key deletedapi_key.deletedDeveloper IDKey IDDashboard key deletion
Plugin createdplugin.createdDeveloper IDPlugin IDDashboard plugin creation
Plugin updatedplugin.updatedDeveloper IDPlugin IDDashboard plugin update
Plugin deletedplugin.deletedDeveloper IDPlugin IDDashboard plugin deletion

Usage

The audit helper is in lib/security/audit.ts:

logAudit({
  action: "api_key.created",
  actor: admin.id,
  target: newKey.id,
  metadata: {
    ...getRequestMeta(req),
    keyName: parsed.data.name,
  },
});

getRequestMeta(req) extracts the client IP and user agent from the request headers.

Querying Audit Logs

Audit logs are stored in PostgreSQL and can be queried directly:

-- all actions by a specific developer
SELECT * FROM audit_logs WHERE actor = 'dev_uuid' ORDER BY created_at DESC;

-- all API key events in the last 24 hours
SELECT * FROM audit_logs
WHERE action LIKE 'api_key.%'
  AND created_at > NOW() - INTERVAL '24 hours';

-- login events with IP addresses
SELECT action, actor, metadata->>'ip' AS ip, created_at
FROM audit_logs
WHERE action = 'developer.login'
ORDER BY created_at DESC;

Extending Audit Coverage

To add audit logging to a new endpoint:

  1. Import logAudit and getRequestMeta from lib/security/audit
  2. Choose a descriptive action name following the resource.verb pattern
  3. Call logAudit() after the operation succeeds (do not await it)
import { logAudit, getRequestMeta } from "@/lib/security/audit";

// after the operation succeeds
logAudit({
  action: "resource.updated",
  actor: admin.id,
  target: resourceId,
  metadata: getRequestMeta(req),
});

Retention

Audit logs accumulate over time. For production deployments, consider:

  • Setting up a cron job or scheduled task to archive or delete logs older than your retention period
  • Exporting logs to an external SIEM or log management service for long-term storage and alerting
  • Adding indexes on action and actor columns if query performance degrades

On this page