Tutorial - Audit a Trace
Goal: produce a trace, connect it to AIR and source, then generate an audit report.
Trace audit (TA-1) verifies the consistency of a run. It is not a legal proof, cryptographic signature, or automatic compliance claim.
What You Will Test
| Step | Expected Result |
|---|---|
| Compile | explicit AIR |
| Run | a trace |
| Audit | an ok report or diagnostics |
| Export | a bounded export when the report is ok |
| Inspect | a readable summary without rerunning the program |
1. Create a Simple Program
mkdir -p audit-demo
cd audit-demo
module examples.audit_demo
strategy RunAuditDemo
gives Text
do
show
with message as "audit demo"
give "done"
2. Compile to AIR
touba compile audit-demo.tb --out audit-demo.air.json
Compilation starts nothing. It produces the artifact consumed by the runtime.
3. Run with a Separate Trace
touba run audit-demo.air.json \
--trace-out audit-demo.trace.json \
--output all
Expected output:
audit demo
audit-demo.trace.json contains runtime events.
4. Audit Trace, AIR, and Source
touba audit \
--trace audit-demo.trace.json \
--air audit-demo.air.json \
--source audit-demo.tb \
--retention-class project_audit \
--redaction-policy no_secrets_no_raw_prompts_no_memory_content
Expected output, in substance:
Touba Trace Audit trace-audit-validation-v1
Status ok
Diagnostics ok
If trace and AIR do not refer to the same module, the report must refuse.
5. Produce a Bounded Export
touba audit \
--trace audit-demo.trace.json \
--air audit-demo.air.json \
--source audit-demo.tb \
--retention-class project_audit \
--redaction-policy no_secrets_no_raw_prompts_no_memory_content \
--export audit-demo.export.json
The export is written only when the report is ok.
6. Inspect the Export
touba inspect --trace-audit audit-demo.export.json
Touba should display:
- export type;
- related run;
- status;
- retention class;
- redaction policy;
- diagnostics.
inspect does not rerun the program, read secrets, or prove compliance with a
regulatory framework.
Reject an AIR mismatch
Keep the original trace and source intact. Compile a second program with the same module identity but a different result, then audit the original trace against it. A matching module name is not sufficient: the complete AIR digest must match.
module examples.audit_demo
strategy RunAuditDemo
gives Text
do
show
with message as "audit demo"
give "changed"
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
const original = readFileSync("audit-demo.trace.json", "utf8");
const child = spawnSync("touba", ["audit", "--trace", "audit-demo.trace.json", "--air", "changed.air.json",
"--source", "changed.tb", "--export", "refused.export.json", "--output", "json"], { encoding: "utf8" });
assert.equal(child.status, 1, child.stderr);
const audit = JSON.parse(child.stdout);
assert.equal(audit.validationReport.status, "failed");
assert.ok(audit.validationReport.diagnostics.some(item => item.code === "TraceAirDigestMismatch"));
assert.equal(existsSync("refused.export.json"), false);
assert.equal(readFileSync("audit-demo.trace.json", "utf8"), original);
console.log("AIR_MISMATCH_REFUSED_ORIGINAL_TRACE_PRESERVED");
touba compile changed.tb --out changed.air.json
node check-refusal.mjs
Validated Contract
Trace audit makes the link between trace, AIR, source, redaction, and export observable and repeatable. The report is an engineering artifact for reviewing, comparing, and preserving an execution.
Keep and archive the journal
Execution also stores events in .touba/traces.sqlite. Request a lightweight
reference to read events in pages:
touba run audit-demo.air.json --output json-reference > run.json
In VS Code, open run.json, run Touba: Render Trace, and select
.touba/traces.sqlite. Next page continues reading.
After your checks, preview and archive successful runs:
touba trace archive --store .touba/traces.sqlite
mkdir -m 700 archives
touba trace archive --store .touba/traces.sqlite --destination archives/audit.sqlite --apply
Keep the archive: the same references can be read with --store archives/audit.sqlite.
Paused, failed and interrupted runs stay in the active journal. For a project
server, archive its complete state with the server stopped, keeping traces
and continuations together.