feat(audit): Add core audit logging infrastructure
- Add AuditLogger class with rotation support - Add audit configuration to config schema - Instrument tool execution with full audit logging - Instrument session lifecycle (create, message, delete, transfer, compact) - Add audit logger initialization in daemon - Add cron scheduler audit logging Audit events captured: - tool.start/success/error/denied - session.create/message/delete/transfer/compact - cron.trigger/add/remove All logs go to ~/.local/share/flynn/audit.log (JSON lines) with rotation (10MB files, 30-day retention)
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
export type AuditLevel = 'debug' | 'info' | 'warn' | 'error';
|
||||
|
||||
export type AuditEventType =
|
||||
// Tool execution
|
||||
| 'tool.start' | 'tool.success' | 'tool.error' | 'tool.denied'
|
||||
// Session lifecycle
|
||||
| 'session.create' | 'session.message' | 'session.delete' | 'session.transfer' | 'session.compact'
|
||||
// Automation - Cron
|
||||
| 'cron.trigger' | 'cron.sent' | 'cron.add' | 'cron.remove'
|
||||
// Automation - Webhook
|
||||
| 'webhook.receive' | 'webhook.sent' | 'webhook.not_found' | 'webhook.denied'
|
||||
// Automation - Heartbeat
|
||||
| 'heartbeat.cycle' | 'heartbeat.check' | 'heartbeat.fail' | 'heartbeat.recover'
|
||||
// Automation - Gmail
|
||||
| 'gmail.poll' | 'gmail.new_email' | 'gmail.error'
|
||||
// System events
|
||||
| 'system.start' | 'system.stop' | 'system.config';
|
||||
|
||||
export interface AuditEvent {
|
||||
timestamp: number;
|
||||
level: AuditLevel;
|
||||
event_type: AuditEventType;
|
||||
event: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface AuditConfig {
|
||||
enabled: boolean;
|
||||
path: string;
|
||||
max_size_mb: number;
|
||||
keep_days: number;
|
||||
levels: {
|
||||
tools: AuditLevel;
|
||||
sessions: AuditLevel;
|
||||
automation: AuditLevel;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AuditQuery {
|
||||
start_time?: number;
|
||||
end_time?: number;
|
||||
event_types?: AuditEventType[];
|
||||
session_id?: string;
|
||||
tool_name?: string;
|
||||
level?: AuditLevel;
|
||||
}
|
||||
|
||||
export interface ToolStartEvent {
|
||||
tool_name: string;
|
||||
tool_args: unknown;
|
||||
session_id?: string;
|
||||
channel?: string;
|
||||
sender?: string;
|
||||
agent_tier?: string;
|
||||
}
|
||||
|
||||
export interface ToolSuccessEvent {
|
||||
tool_name: string;
|
||||
result: { success: boolean; output: string; error?: string };
|
||||
duration_ms: number;
|
||||
session_id?: string;
|
||||
}
|
||||
|
||||
export interface ToolErrorEvent {
|
||||
tool_name: string;
|
||||
error: string;
|
||||
duration_ms: number;
|
||||
reason?: string;
|
||||
session_id?: string;
|
||||
}
|
||||
|
||||
export interface ToolDeniedEvent {
|
||||
tool_name: string;
|
||||
reason: string;
|
||||
session_id?: string;
|
||||
denial_type: 'policy' | 'hook' | 'not_found';
|
||||
}
|
||||
|
||||
export interface SessionCreateEvent {
|
||||
session_id: string;
|
||||
frontend: string;
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
export interface SessionMessageEvent {
|
||||
session_id: string;
|
||||
role: 'user' | 'assistant';
|
||||
content_length: number;
|
||||
}
|
||||
|
||||
export interface SessionDeleteEvent {
|
||||
session_id: string;
|
||||
message_count: number;
|
||||
}
|
||||
|
||||
export interface SessionCompactEvent {
|
||||
session_id: string;
|
||||
messages_before: number;
|
||||
messages_after: number;
|
||||
tokens_before: number;
|
||||
tokens_after: number;
|
||||
}
|
||||
|
||||
export interface CronTriggerEvent {
|
||||
job_name: string;
|
||||
schedule: string;
|
||||
message: string;
|
||||
output_channel: string;
|
||||
output_peer: string;
|
||||
}
|
||||
|
||||
export interface WebhookReceiveEvent {
|
||||
webhook_name: string;
|
||||
body: string;
|
||||
signature_verified: boolean;
|
||||
output_channel: string;
|
||||
output_peer: string;
|
||||
}
|
||||
|
||||
export interface HeartbeatCycleEvent {
|
||||
interval_ms: number;
|
||||
checks: string[];
|
||||
healthy: boolean;
|
||||
consecutive_failures: number;
|
||||
}
|
||||
|
||||
export interface HeartbeatCheckEvent {
|
||||
check_name: string;
|
||||
healthy: boolean;
|
||||
message: string;
|
||||
duration_ms: number;
|
||||
}
|
||||
|
||||
export interface HeartbeatFailEvent {
|
||||
checks_failed: string[];
|
||||
consecutive_failures: number;
|
||||
threshold: number;
|
||||
}
|
||||
|
||||
export interface HeartbeatRecoverEvent {
|
||||
consecutive_failures_before: number;
|
||||
}
|
||||
|
||||
export interface GmailPollEvent {
|
||||
mode: 'watch' | 'poll';
|
||||
interval_ms?: number;
|
||||
emails_processed: number;
|
||||
new_emails: number;
|
||||
}
|
||||
|
||||
export interface GmailNewEmailEvent {
|
||||
email_id: string;
|
||||
from: string;
|
||||
subject: string;
|
||||
labels: string[];
|
||||
}
|
||||
Reference in New Issue
Block a user