@zappzarapp/audit-logger
v1.0.0
Published
GDPR-compliant audit logging with injectable encryption, configurable storage, and tamper-proof checksums
Maintainers
Readme
⚡ @zappzarapp/audit-logger
GDPR-compliant audit logging for Node.js/TypeScript with injectable encryption, configurable storage, and tamper-proof checksums.
Features
- GDPR compliant - Supports Art. 15, 17, 30, 32, 33
- Injectable encryption - AppEncryption (AES-256-GCM) or DatabaseEncryption
- Tamper-proof - SHA-256 checksums with
verify()method - Configurable - Custom table name, optional file logging
- Null Object -
NullAuditLoggerfor environments without audit requirements - Zero runtime dependencies - Only uses
node:cryptoandnode:fs(built-in) - Both PostgreSQL and MariaDB - Migration SQL included, dialect-aware SQL generation
- DB-agnostic -
QueryExecutorinterface, no driver dependency
Installation
npm install @zappzarapp/audit-loggerQuick Start
import { AuditLogger } from '@zappzarapp/audit-logger';
const auditLogger = new AuditLogger(
executor, // Your QueryExecutor implementation
process.env.ENCRYPTION_KEY!, // Encryption key
'postgres' // Database dialect: 'postgres' | 'mysql'
);
// Log a data access event
await auditLogger.log({
action: 'user.view',
entityType: 'user',
entityId: 123,
userId: currentUserId,
ipAddress: req.ip,
userAgent: req.headers['user-agent'],
});
// Log authentication
await auditLogger.logAuth(
'login.success',
userId,
{},
req.ip,
req.headers['user-agent']
);
// Log admin action
await auditLogger.logAdmin('role.granted', adminId, 'user', targetUserId, {
role: 'moderator',
});
// Query logs
const logs = await auditLogger.getLogsForEntity('user', 123);
const userLogs = await auditLogger.getLogsForUser(userId);
// Verify integrity
for (const log of logs) {
if (!auditLogger.verify(log)) {
// Tampered entry detected!
}
}QueryExecutor Interface
This package does not depend on any database driver. Instead, implement the
QueryExecutor interface to wrap your existing connection:
import type { QueryExecutor } from '@zappzarapp/audit-logger';
// Example: wrapping a pg Pool
const executor: QueryExecutor = {
async query(sql, params) {
const result = await pool.query(sql, params);
return result.rows;
},
async execute(sql, params) {
const result = await pool.query(sql, params);
return { affectedRows: result.rowCount ?? 0 };
},
};Configuration
import {
AuditLogger,
AppEncryption,
DatabaseEncryption,
NullAuditLogger,
} from '@zappzarapp/audit-logger';
// Full configuration
const auditLogger = new AuditLogger(
executor,
process.env.ENCRYPTION_KEY!,
'postgres',
{
encryption: new AppEncryption(), // default (AES-256-GCM via node:crypto)
tableName: 'audit_logs', // default table name
logFilePath: '/var/log/audit.log', // optional file logging (null = disabled)
}
);
// Using database-level encryption (for existing encrypt_text() setups)
const dbLogger = new AuditLogger(
executor,
process.env.ENCRYPTION_KEY!,
'postgres',
{ encryption: new DatabaseEncryption() }
);
// Disable audit logging (Null Object pattern)
const nullLogger = new NullAuditLogger();Database Setup
Apply the migration for your database:
- PostgreSQL:
migrations/postgresql/audit_logs.sql - MariaDB:
migrations/mariadb/audit_logs.sql
Documentation
- GDPR Compliance - GDPR articles covered, purge/retention guidance
- Database Encryption - Migration from DB-level encryption
Development
make install # Install dependencies
make test # Run tests
make typecheck # TypeScript type checking
make lint # ESLint
make build # Build TypeScript
make check # All quality checksLicense
MIT
