Audit Logging - nself-org/nchat GitHub Wiki
Tamper-proof audit logging with cryptographic integrity verification and compliance-ready export formats.
- Overview
- Audit Log Features
- Tamper-Proof Architecture
- Log Categories
- Searching and Filtering
- Export Formats
- Compliance
- Best Practices
nself-chat provides enterprise-grade audit logging with cryptographic integrity guarantees. Every action is logged in an immutable, tamper-proof chain.
- Tamper-Proof: Cryptographic hash chains prevent modification
- Comprehensive: Logs all user, admin, and system actions
- Searchable: Advanced filtering and full-text search
- Exportable: Multiple compliance formats (JSON, CSV, Syslog, CEF)
- Integrity Verification: Verify log chain hasn't been tampered with
- Retention Policies: Automated retention and archival
- Real-Time: Immediate logging with batch processing
Every audit entry includes:
{
// Identification
id: "uuid",
blockNumber: 1234,
timestamp: "2026-01-31T12:00:00Z",
// Action Details
action: "user_login",
category: "security",
severity: "info",
description: "User logged in successfully",
success: true,
// Actor (who did it)
actor: {
id: "user-123",
type: "user",
ipAddress: "192.168.1.1"
},
// Resource (what was affected)
resource: {
type: "user",
id: "user-123",
name: "[email protected]"
},
// Cryptographic Proof
entryHash: "sha256:abc123...",
previousHash: "sha256:def456...",
// Metadata
metadata: {
userAgent: "Mozilla/5.0...",
location: "San Francisco, CA"
}
}Block 1: [Data] → Hash A →
Block 2: [Data + Hash A] → Hash B →
Block 3: [Data + Hash B] → Hash C →
...
Each block contains:
- Current event data
- Hash of previous block
- Sequential block number
- Calculated hash of entire block
Result: Any modification breaks the chain and is instantly detectable.
hash =
SHA - 256(blockNumber + previousHash + timestamp + action + actorId + resourceId + description)// Verify entire chain
const verification = await verifyAuditIntegrity()
console.log({
isValid: true,
totalEntries: 10000,
verifiedEntries: 10000,
compromisedBlocks: [],
chainMetadata: {
chainId: 'uuid',
genesisHash: 'sha256:...',
currentHash: 'sha256:...',
},
})- Immutability: Once written, cannot be modified
- Ordering: Strict chronological order maintained
- Completeness: Missing blocks detected immediately
- Authenticity: Cryptographic proof of authenticity
Category: 'user'
Events: -user_created -
user_updated -
user_deleted -
user_login -
user_logout -
user_password_changed -
user_email_verified -
user_profile_updatedCategory: 'security'
Events: -login_success -
login_failed -
logout -
password_reset -
mfa_enabled -
mfa_disabled -
session_expired -
suspicious_activity -
sso_login -
api_key_createdCategory: 'admin'
Events: -role_created -
role_updated -
role_deleted -
role_assigned -
permission_granted -
permission_revoked -
user_banned -
user_unbanned -
settings_updated -
integration_configuredCategory: 'message'
Events: -message_sent -
message_edited -
message_deleted -
message_pinned -
message_reported -
reaction_addedCategory: 'channel'
Events: -channel_created -
channel_updated -
channel_deleted -
channel_archived -
user_joined -
user_left -
user_invited -
user_kickedAccess Admin Dashboard → Security → Audit Log
filter = {
startDate: new Date('2026-01-01'),
endDate: new Date('2026-01-31'),
}filter = {
actorIds: ['user-123', 'user-456'],
actorTypes: ['user', 'system', 'api'],
}filter = {
actions: ['user_login', 'user_logout'],
categories: ['security', 'admin'],
severities: ['critical', 'error', 'warning'],
}filter = {
resourceTypes: ['user', 'channel', 'message'],
resourceIds: ['user-123'],
}filter = {
searchText: '[email protected]',
}const filter = {
startDate: new Date('2026-01-01'),
endDate: new Date('2026-01-31'),
categories: ['security', 'admin'],
severities: ['error', 'critical'],
success: false, // Only failed actions
searchText: 'login',
sortBy: 'timestamp',
sortOrder: 'desc',
limit: 50,
offset: 0,
}
const results = await searchTamperProofLogs(filter){
"exportedAt": "2026-01-31T12:00:00Z",
"chainMetadata": {
"chainId": "uuid",
"totalEntries": 1000
},
"entries": [
{
"id": "uuid",
"timestamp": "2026-01-31T12:00:00Z",
"action": "user_login",
"actor": { "id": "user-123" },
"entryHash": "sha256:..."
}
]
}Block,Timestamp,Action,Actor,Category,Severity,Success,Hash
1234,2026-01-31 12:00:00,user_login,user-123,security,info,true,sha256:abc...<14>1 2026-01-31T12:00:00Z nchat audit - - - user_login: User logged in successfully
<14>1 2026-01-31T12:01:00Z nchat audit - - - channel_created: Channel created
CEF:0|nself|nchat|1.0|user_login|User logged in|2|act=user_login suser=user-123 outcome=success
LEEF:1.0|nself|nchat|1.0|user_login|devTime=Jan 31 2026 12:00:00|action=user_login usrName=user-123
- Navigate to Audit Log
- Apply desired filters
- Click Export → Select format
- File downloads automatically
// Export last 30 days as JSON
const data = await getTamperProofAuditService().exportLogs(
{
startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
endDate: new Date(),
},
'json'
)
// Save to file
fs.writeFileSync('audit-log.json', data)Requirements:
- Logging of all administrative actions ✅
- Immutable audit trail ✅
- Regular integrity verification ✅
- Secure log storage ✅
- Access controls on logs ✅
Configuration:
{
retentionDays: 365,
enableTamperProof: true,
logAllAdminActions: true,
requireMFA: true
}Requirements:
- Log data access and modifications ✅
- Right to deletion (with exceptions) ✅
- Data export capability ✅
- Retention policies ✅
Configuration:
{
logPersonalDataAccess: true,
retentionDays: 730, // 2 years
allowLegalHold: true,
exportFormats: ['json', 'csv']
}Requirements:
- Access logs for PHI ✅
- 6-year retention ✅
- Tamper detection ✅
- Audit log reviews ✅
Configuration:
{
retentionDays: 2190, // 6 years
enableTamperProof: true,
logAllDataAccess: true,
monthlyReviews: true
}Requirements:
- Log all access to cardholder data ✅
- Daily log reviews ✅
- 1-year online, 3-year total retention ✅
- Integrity verification ✅
Configuration:
{
retentionDays: 365,
archiveRetentionDays: 1095,
dailyIntegrityCheck: true,
alertOnFailure: true
}Schedule automated integrity checks:
# Daily verification (cron)
0 2 * * * /usr/bin/verify-audit-integrity// Automated verification
setInterval(
async () => {
const result = await verifyAuditIntegrity()
if (!result.isValid) {
alertSecurityTeam(result)
}
},
24 * 60 * 60 * 1000
) // DailyConfigure appropriate retention:
// Development
retentionDays: 30
// Production
retentionDays: 365
// Compliance (HIPAA)
retentionDays: 2190 // 6 years
// Legal Hold
legalHold: true // Never deleteSet up alerts for critical events:
const criticalEvents = [
'user_banned',
'role_deleted',
'settings_updated',
'sso_connection_deleted',
'audit_integrity_compromised',
]
criticalEvents.forEach((event) => {
subscribeToAuditEvent(event, async (entry) => {
await notifySecurityTeam(entry)
await createIncident(entry)
})
})Restrict audit log access:
// Only admins and compliance officers
permissions: {
'admin:audit_log': ['admin', 'compliance-officer'],
'admin:audit_export': ['admin', 'compliance-officer'],
'admin:audit_delete': ['owner'] // Never allow
}Schedule periodic reviews:
- Daily: Security events (failed logins, suspicious activity)
- Weekly: Admin actions (role changes, user bans)
- Monthly: All categories (comprehensive review)
- Quarterly: Integrity verification
- Annually: Retention policy compliance
Audit logs should be backed up separately:
# Automated backup
0 3 * * * /usr/bin/backup-audit-logs --destination s3://audit-backup/
# Verify backup integrity
0 4 * * * /usr/bin/verify-backup-integrityconst stats = await getTamperProofAuditService().getStatistics({
startDate: new Date('2026-01-01'),
endDate: new Date('2026-01-31'),
})
console.log({
totalEvents: 10000,
eventsByCategory: {
security: 3500,
admin: 1200,
user: 4000,
message: 1300,
},
failureRate: 0.02, // 2% failure rate
topActors: [
{ actorId: 'user-123', count: 450 },
{ actorId: 'user-456', count: 320 },
],
})const failedLogins = await searchTamperProofLogs({
actions: ['login_failed'],
startDate: new Date(Date.now() - 24 * 60 * 60 * 1000),
sortBy: 'timestamp',
sortOrder: 'desc',
})const adminActions = await searchTamperProofLogs({
actorIds: ['admin-123'],
categories: ['admin'],
startDate: new Date('2026-01-01'),
})const incidents = await searchTamperProofLogs({
categories: ['security'],
severities: ['critical', 'error'],
success: false,
})Symptom: Verification reports compromised blocks
Diagnosis:
- Review verification errors
- Identify compromised block numbers
- Check for system issues (corruption, hardware failure)
Resolution:
- Alert security team immediately
- Investigate root cause
- Restore from backup if necessary
- Review security posture
Symptom: Slow log queries
Solutions:
- Add indexes on frequently queried fields
- Implement pagination (use offset/limit)
- Use time-based partitioning
- Archive old logs
Symptom: Audit logs consuming excessive storage
Solutions:
- Implement retention policies
- Enable compression
- Archive to cold storage
- Review logging verbosity
Last Updated: January 2026 Version: 1.0.0