Audit logs provide a comprehensive record of all actions performed in Frontier. Every user interaction, permission check, and system event is recorded with details about who did what, when, and to which resource.
app.user.created - New user registeredapp.user.updated - User profile modifiedapp.user.deleted - User account deletedapp.user.listed - User list accessedapp.serviceuser.created - Service user createdapp.serviceuser.deleted - Service user removed
app.group.created - Group createdapp.group.updated - Group modifiedapp.group.deleted - Group removedapp.group.members.removed - Members removed from group
For advanced analysis, query the database directly:
-- Find all actions by a specific userSELECT * FROM audit_logsWHERE actor->>'id' = 'user_123abc'ORDER BY created_at DESCLIMIT 100;-- Count actions by type in the last 24 hoursSELECT action, COUNT(*) as countFROM audit_logsWHERE created_at > NOW() - INTERVAL '24 hours'GROUP BY actionORDER BY count DESC;-- Find failed permission checksSELECT *FROM audit_logsWHERE action = 'app.permission.checked' AND metadata->>'status' = 'false'ORDER BY created_at DESC;-- Find organization deletionsSELECT *FROM audit_logsWHERE action = 'app.organization.deleted'ORDER BY created_at DESC;-- Find all actions in a specific organizationSELECT *FROM audit_logsWHERE org_id = 'org_123abc' AND created_at > '2024-03-01'ORDER BY created_at DESC;
-- Find users with multiple organizations accessedSELECT actor->>'id' as user_id, actor->>'name' as user_email, COUNT(DISTINCT org_id) as org_count, COUNT(*) as total_actionsFROM audit_logsWHERE created_at > NOW() - INTERVAL '1 hour'GROUP BY actor->>'id', actor->>'name'HAVING COUNT(DISTINCT org_id) > 5ORDER BY total_actions DESC;
Track permission denied events
-- Find resources users are trying to access without permissionSELECT actor->>'name' as user, target->>'type' as resource_type, metadata->>'permission' as permission, COUNT(*) as denied_countFROM audit_logsWHERE action = 'app.permission.checked' AND metadata->>'status' = 'false' AND created_at > NOW() - INTERVAL '24 hours'GROUP BY actor->>'name', target->>'type', metadata->>'permission'ORDER BY denied_count DESC;
User activity timeline
-- Show all actions by a user in chronological orderSELECT created_at, action, target->>'type' as target_type, target->>'name' as target_name, metadataFROM audit_logsWHERE actor->>'id' = 'user_123abc' AND created_at > NOW() - INTERVAL '7 days'ORDER BY created_at DESC;
Organization membership changes
-- Track who was added/removed from organizationsSELECT created_at, action, org_id, actor->>'name' as performed_by, target->>'name' as affected_user, metadataFROM audit_logsWHERE action IN ( 'app.organization.member.created', 'app.organization.member.deleted')ORDER BY created_at DESC;
Most active users
-- Find users performing the most actionsSELECT actor->>'name' as user, COUNT(*) as action_count, COUNT(DISTINCT org_id) as orgs_accessed, COUNT(DISTINCT DATE(created_at)) as active_daysFROM audit_logsWHERE actor->>'type' = 'user' AND created_at > NOW() - INTERVAL '30 days'GROUP BY actor->>'name'ORDER BY action_count DESCLIMIT 20;
Audit logs can grow large. Implement a retention policy:
-- Archive logs older than 90 days to separate tableCREATE TABLE audit_logs_archive ASSELECT * FROM audit_logsWHERE created_at < NOW() - INTERVAL '90 days';-- Delete archived logs from main tableDELETE FROM audit_logsWHERE created_at < NOW() - INTERVAL '90 days';
#!/bin/bash# Run monthly on the 1st at 2 AMpsql $DATABASE_URL <<SQL -- Copy to archive INSERT INTO audit_logs_archive SELECT * FROM audit_logs WHERE created_at < NOW() - INTERVAL '90 days' ON CONFLICT DO NOTHING; -- Delete from main table DELETE FROM audit_logs WHERE created_at < NOW() - INTERVAL '90 days';SQLecho "Archived audit logs older than 90 days"
Alert when a user repeatedly tries to access unauthorized resources:
SELECT actor->>'id' as user_id, COUNT(*) as failed_checksFROM audit_logsWHERE action = 'app.permission.checked' AND metadata->>'status' = 'false' AND created_at > NOW() - INTERVAL '5 minutes'GROUP BY actor->>'id'HAVING COUNT(*) > 10;
Administrative action by non-admin
Alert on privilege escalation attempts:
SELECT *FROM audit_logsWHERE action IN ( 'app.role.created', 'app.permission.created', 'app.organization.member.created')AND actor->>'id' NOT IN ( SELECT id FROM users WHERE is_admin = true);
Bulk data access
Alert when someone lists many resources:
SELECT actor->>'name' as user, COUNT(*) as list_operationsFROM audit_logsWHERE action LIKE '%.listed' AND created_at > NOW() - INTERVAL '1 hour'GROUP BY actor->>'name'HAVING COUNT(*) > 100;