Skip to content

Audit Logs

Every LLM call SQLatte makes — intent detection, SQL generation, chat, insights — is recorded, independent of whether usage analytics is enabled. This is the observability trail for cost tracking, compliance, and answering "what did this AI agent actually query."

What's Logged

  • Intent type (intent_detection / sql_generation / chat / insights)
  • Input/output token counts
  • The generated SQL and its risk score (0–100, informational — never blocks execution)
  • Source: ui (default chat), widget (embedded), or mcp — so you can see exactly how much traffic is coming from AI agents versus human users
  • Session and user identifiers, timestamp

Endpoints

Endpoint Method Purpose
/api/audit/logs GET Paginated log entries — filter by session, intent type, date range, or user
/api/audit/summary GET Aggregated token usage and call counts, plus SQL validation metrics (below)
/api/audit/daily-trend GET Call volume over time
/api/audit/top-users GET Highest token/call volume by user
/api/audit/export/csv GET Download filtered logs for billing or compliance review

All audit routes require admin authentication.

/api/audit/summary also reports sql_checked_count, invalid_sql_count, and invalid_sql_ratio — how many generated queries were validated in the period and what fraction failed is_select_only(), a quick signal for whether the LLM is generating a lot of SQL the validator has to reject.

Security Alerts

mcp.security_alerts (off by default) notifies when an AI/MCP-generated query looks sensitive — triggered by either a risk score above risk_threshold, or the query touching a column matching an enabled MCP Masking field_pattern. Every check is best-effort and never blocks the query; it only adds a notification (log always, email if email.enabled: true and notify_emails is set) on top of the existing audit record. See Full Config Reference.

Admin Panel

/admin → Audit Logs, filterable by widget source — useful for answering "how much is the MCP integration costing us" separately from interactive chat usage, since both hit the same LLM billing but originate from very different traffic patterns.

Risk Score Reference

Risk scoring never blocks a query — is_select_only() does that, unconditionally, before the score is even computed. The score is purely a signal logged alongside every call for monitoring:

Range Meaning
0–9 Clean SELECT
10–24 Minor exposure signals (SELECT *, no LIMIT)
25–44 Multiple exposure signals (set operations, deep subqueries, cross joins)
45–79 Dangerous function detected — already blocked
80–100 Multiple dangerous factors — already blocked

See Security Overview for how the score is computed and why blocking and scoring are deliberately separate concerns.