Ask the file a question in plain language.
A question becomes a structured query plan. The plan is validated against an allow-list, turned into SQL by ClairAudit rather than by the model, and run inside your tenant’s row-level security.
Row-level security
The model writes a plan, not SQL.
The plan names an intent, a table, filters, an aggregation, grouping, ordering and a limit. Filters use a fixed set of operators, and relative dates such as “30 days ago” are resolved when the query runs.
How many open high findings are older than 30 days, by engagement?
{
"intent": "open high findings",
"tables": ["findings"],
"filters": [
{
"field": "status",
"op": "eq",
"value": "open"
},
{
"field": "severity",
"op": "eq",
"value": "high"
},
{
"field": "createdAt",
"op": "lt",
"value": "30d-ago"
}
],
"aggregation": "count",
"groupBy": "engagementId",
"limit": 50
} What keeps a question inside its tenant.
- Allow-list
Nine queryable tables
Plans naming anything else are rejected, and field names must match a strict identifier pattern.
- Operators
A closed set of filters
eq, neq, gt, gte, lt, lte, like, in, is null and not null. Aggregations are count, sum, average, minimum and maximum.
- Limit
50 rows by default, 500 at most
Large result sets need a narrower question, not a bigger limit.
- RLS
Executed under row-level security
The query runs in the tenant and user context, so the database itself refuses rows outside it.
- Log
Sessions and queries are recorded
Each query keeps its status, execution time and results, and saved templates can be reused.
Bring an engagement. We will walk the file with you.
A demo covers your audit methodology, the standards you report under, and how agents, citations and review gates would fit your team. Pricing is discussed on the call.