Audit log Preview
Search every action and gateway decision, group rows by request, verify the hash chain and export evidence.
- Filter the audit log by actor, action, outcome and time
- Export rows and download an evidence bundle
- Verify the log has not been altered
- Let an auditor verify a bundle with the published key alone
The audit explorer is being redesigned around facets and request grouping. The query API below is current.
Search
- Open Governance › Audit log. Pick a time range: Last 15 min, Last 1 hour, Last 6 hours, Last 24 hours, Last 3 days, Last 7 days (the default), Last 14 days, Last 30 days, Last 90 days, All time or Custom range.
- Narrow with facets.
Facet Example Actor, Actor type alice,human,agent,clientAction guardrail.save,budget.fallbackResource type, Resource name Agent,hr-helperOutcome, Response code denied,403Subsystem, Service The part of the product that wrote the row, or a connector Finding action, category, engine, family, policy Guardrail findings - Type free text, or
field=value/field!=value, in the search box. Search all fields (the default) matches the action, the actor and every detail value. Search messages matches only each row's one-line message. - Turn on Group by request to see every row one request produced together.
The same search as an API call:
curl -G https://<host>/api/audit/query -H "Authorization: Bearer $TOKEN" \
--data-urlencode 'q=actor=alice outcome=denied' --data-urlencode 'window=24h' \
--data-urlencode 'page_size=50'GET /api/audit/query accepts q, window, since, until, page_size, page_token, order_by, fields, facet, match=all|message and group. window defaults to 7d. One event: GET /api/audit/events/{event_id}.
Export and evidence
GET /api/audit/export?fmt=csv(orfmt=jsonl) exports the filtered rows: 10,000 by default,limitup to 50,000. Requiresaudit.read.- Retention & evidence → Download evidence bundle (or
GET /api/audit/export?fmt=bundle) produces a zip of the whole hash-chained log and a manifest naming every file's SHA-256, the row count, the chain head and the checkpoints. The manifest carries two signatures:- an Ed25519 attestation with the instance's audit signing key, whose public key anyone can have, so a third party can check the bundle with no access to the instance.
- an HMAC with the instance's audit key, kept for existing verifiers. Only the host can check it.
Verify a bundle without instance access
- Get the instance's public audit signing keys once, and keep them:
GET /api/audit/signing-key(requiresaudit.read), or the publicGET /.well-known/liyagent-audit-key.json. Each key lists itsfingerprint(SHA-256 of the raw public key), itsstatusand its validity window (valid_from,valid_until). - Run the standalone verifier. It needs Python 3.9+ and the
cryptographypackage, and nothing from the instance:curl -s https://<host>/.well-known/liyagent-audit-key.json > audit-keys.json python scripts/verify_audit_bundle.py bundle.zip --keys audit-keys.json # or pin one key: --fingerprint <sha256 hex>It checks the Ed25519 signature on the manifest against the published keys, the bundle's date against the key's validity window, every row's hash and link, the archive segments, the anchored checkpoint, and the rows file and evidence files against the manifest. Exit codes:
0intact and signed by a published key,2a finding,3intact but no published key or fingerprint was given to trust the signer by,1unreadable.
The verifier cannot check the HMAC signatures on checkpoints and on rows redacted by an erasure. Those need the instance's key. tiq audit verify bundle.zip (also liya audit verify) checks everything on the host with --local-key, and the attestation with --audit-keys audit-keys.json.
Rotate the audit signing key
POST /api/audit/signing-key/rotate (requires governance.write, audited as audit.signing_key.rotate) makes a new active key. The old key stops signing at once, its private half is deleted and its validity window ends. Its public key stays listed, so the bundles it signed still verify. If the key leaked, send {"compromised": true, "reason": "…"}: the old key is listed as revoked, and verifiers refuse what it signed.
Integrity and retention
- Rows are hash-chained. Verify chain now, or
GET /api/audit/verify(requiresaudit.read, rate-limited), walks the live chain with the instance's key and names each edited, deleted or reordered row and any forged checkpoint. - Keep rows for (days) and Legal hold are set under Retention & evidence (
GET/PUT /api/audit/retention, wherePUTrequiresadmin.write).
Request bodies are never captured on sign-in, token, OAuth or secret endpoints, whatever the capture settings.