Tracevault
OverviewInstallWritingQueryData model

On the same app object

The read API ships as audit.query on the app returned by startTracevault, and as audit.getScope("name").query per scope. It is deliberately narrow: equality filters on scalar columns (including generated outcome, error_code, severity), an occurred_at window, and deterministic pagination. Aggregations, JSONB path probes, and joins belong in raw SQL.

read.ts
const recent = await audit.query.findMany({
  event: "product.price.updated",
  from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
  limit: 100,
})

const scoped = await audit.getScope("users").query.findMany({
  event: "user.profile.updated",
  limit: 50,
})

const one = await audit.query.findById("uuid-here")
const total = await audit.query.count({ actorType: "user", environment: "prod" })

Scoped reads

Use getScope("users").query instead of a separate reader factory. All scopes share the app's read and write pools.

scoped-read.ts
const rows = await audit.getScope("users").query.findMany({
  event: "user.profile.updated",
  errorsOnly: true,
  limit: 50,
})

Error-oriented views

errorsOnly: true matches rows where outcome = 'failure' or severity is in SEVERITIES_FOR_ERRORS_ONLY_FILTER (exported from tracevault). Filters are ANDed together.

errors.ts
// failures by outcome OR high-severity rows (see SEVERITIES_FOR_ERRORS_ONLY_FILTER)
await audit.query.findMany({
  errorsOnly: true,
  limit: 50,
})

findMany / count filters

Unknown keys throw ValidationError. String filters are plain equality — no LIKE. from / to must not be inverted.

FieldApplies toNotes
eventfindMany, countExact match
actorId, actorTypefindMany, countExact match
targetId, targetTypefindMany, countExact match
correlationId, requestIdfindMany, countExact match
environmentfindMany, countExact match
outcome, errorCode, severityfindMany, countGenerated columns (migrations 002–003)
severitiesfindMany, countIN list, max 16, no duplicates
errorsOnlyfindMany, countfailure outcome or high severities
modefindMany, countsync | async
from, tofindMany, countInclusive bounds on occurredAt
limit, offset, orderfindMany onlylimit 1–500 (default 50), order asc|desc on (occurred_at, id)

Lifecycle

Call await audit.close() once: it drains every scope's write queue, then ends Tracevault-owned pools. Injected pool / readPool are not ended. After close, emit and query throw TracevaultError.

Types

AuditRecord, AuditQueryFilters, DOCUMENTED_SEVERITY_LEVELS, and related exports live on the main tracevault entry — no separate query package in 1.x.

Next

Column reference on Data model. setup on Install.