TypeScript package @truvity/audit¶
yarn add @truvity/audit # after the registry scope in the SDK overview
A typed query client, a qualifier box compiled to a typed filter, and records as sentences. It mirrors the Go query client. React hooks live in @truvity/audit-react. Set the registry scope once, in the SDK overview.
The query service's grants decide who reads what: see read the trail and the API reference.
The client¶
import { createConnectTransport } from "@connectrpc/connect-web";
import { createQueryClient } from "@truvity/audit";
const audit = createQueryClient(createConnectTransport({
baseUrl: "https://audit-query.example.com",
jsonOptions: { useProtoFieldName: true },
interceptors: [(next) => async (req) => {
req.header.set("Authorization", `Bearer ${await session.token()}`);
return next(req);
}],
}));
const page = await audit.search({ profile: "security", limit: 50 });
The client sends what your transport sends, so the transport carries the bearer token. useProtoFieldName matches the JSON in the API reference.
Qualifiers: a typed filter from a box¶
compileQualifiers(text) compiles typed text into the Filter the service takes. Every token names a field or is an error.
import { compileQualifiers } from "@truvity/audit";
const { filter, errors } = compileQualifiers("action:wallet.issue* outcome:failure,denied -actor.kind:service since:24h");
const page = await audit.search({ profile: "security", filter: [filter], limit: 50 });
| token | means |
|---|---|
actor:alice |
the field, equal to the value |
action:wallet.issue* |
a trailing * is a prefix |
outcome:failure,denied |
a comma is any of |
-outcome:success |
a leading - excludes |
target:credential:c-1 |
a target by type and id; target:credential is any of that type |
data.channel:web |
a filterable property of the data slot, by its path |
since:24h, until:2026-09-18 |
when the event occurred: a duration (24h, 7d) or a date |
"request:a b" |
quotes keep a value with spaces together |
The fields are id, action, source, operation, outcome, tenant, actor, actor.kind, subject, subject.kind, request, trace, client, observer and meter.
qualifierNames lists them for help text.
errors holds one message per unreadable token, and the filter omits it. qualifier(field, value, exclude?) writes the token that narrows to, or away from, one value.
Records as sentences¶
audit messages <catalogue.yaml> prints a catalogue's sentences as JSON at build time. Ship them with your console.
import { Sentencer } from "@truvity/audit";
import shop from "./audit-sentences.json";
const sentences = new Sentencer([shop], "en");
sentences.sentence(record); // "Alice refused order 1042"
sentences.summary(record); // what the action is, for a tooltip
commonSentences covers the audit.* actions and is always included. A record uses its own catalogue version's template, else the newest version with the action. A template that fails falls back to the action's summary, then to the action name.
Paging and one record¶
Pass cursor: page.cursors?.next to the next search until a page comes back short or without one. Keep the last cursor to fetch later records. audit.get({ profile, id }) returns one record with its provenance.