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:
William Valentin
2026-02-11 15:58:07 -08:00
parent fae3565480
commit d62e836b5d
12 changed files with 732 additions and 1 deletions
+24
View File
@@ -1,5 +1,6 @@
import type { Message } from '../models/types.js';
import type { SessionStore } from './store.js';
import { auditLogger } from '../audit/index.js';
export interface Session {
id: string;
@@ -23,6 +24,15 @@ export class ManagedSession implements Session {
};
this.history.push(messageWithTimestamp);
this.store.addMessage(this.id, messageWithTimestamp);
auditLogger?.sessionMessage({
session_id: this.id,
role: message.role,
content_length: typeof message.content === 'string'
? message.content.length
: JSON.stringify(message.content).length,
});
return messageWithTimestamp;
}
@@ -31,8 +41,14 @@ export class ManagedSession implements Session {
}
clear(): void {
const messageCount = this.history.length;
this.history = [];
this.store.clearSession(this.id);
auditLogger?.sessionDelete({
session_id: this.id,
message_count: messageCount,
});
}
/**
@@ -67,6 +83,12 @@ export class SessionManager {
const history = this.store.getMessages(id);
session = new ManagedSession(id, this.store, history);
this.sessions.set(id, session);
auditLogger?.sessionCreate({
session_id: id,
frontend,
user_id: userId,
});
}
return session;
@@ -88,6 +110,8 @@ export class SessionManager {
for (const message of history) {
toSession.addMessage(message);
}
auditLogger?.sessionTransfer(fromSession.id, toSession.id, history.length);
}
listSessions(): string[] {