Audit and export

Reading a finished run — for an auditor, or for someone who needs the data out.

Routes: /process/[processId]/audit, /process/[processId]/export APIs: canonical process read with audit authority and /api/process/{id}/export


Audit

What it returns

A canonical public Process view with field audit and presentation—not private machine continuations, encrypted handles or the raw aggregate.

Permission

processes:audit, deliberately not processes:read_all.

read_all also confers write. An auditor needs to read every run without being able to change one, so audit exists as a read-only cross-process grant.

What the audit trail contains

Meaningful field changes attributed by the canonical service:

{ at: "2026-07-27T00:53:09Z", userId: "dev-user", stepKey: "input",
  changes: { name: "Test Partner", contractAddress: "0x1234" } }

Nothing is ever overwritten. Correcting a field appends a second entry rather than replacing the first, so the trail shows what was entered and what it was changed to.

userId: "system" (SYSTEM_STEP_CONTEXT_USER_ID) marks writes made by automation rather than a person. It is the only way to distinguish a machine write from a human one.


Execution and presentation in audit

Execution remains pinned to its immutable definition. Public views can overlay current presentation; that overlay is not historical execution authority. Records compare relevant presentation fields explicitly when reporting divergence. Offline migration converts old full-bucket audit once and preserves missing historical evidence rather than inventing timestamps or actors.


Export

Turns a process into a tabular structure suitable for rendering or download.

Shapes

ProcessExportRow    { label, key, value, files?, list? }
ProcessExportListTable  { columns[], rows: ProcessExportCell[][] }
ProcessExportCell   { key, value, files?, list? }

files is present when the field was an upload, enabling download from the export UI. list is present when the field was an item_list, rendered as a nested table — and because ProcessExportCell itself carries list, nesting recurses.

Files: platform/contracts/src/export/, applications/main/src/services/export/.

UI

ProcessExportButton.tsx in the runner. /process/[processId]/export renders the tables.

Word downloads

POST /api/export/docx-template fills a bundled .docx (docxtemplater placeholders and loops) with a JSON applications/main/data object the client supplies. Requires processes:read. Registered keys live under applications/main/src/assets/docx-templates/ (e.g. spell-strategic-overview for the Spell Request strategic package). Uploadable templates are not wired yet; the same fill service is meant to resolve a stored template the same way later.


Records vs audit

This page covers the per-process view: the raw audit dump and the export for one run.

The cross-process archive — every run with a derived outcome, checkbox tallies, participants, drift detection and bundle export — is records at /records. Use audit to inspect one run in full; use records to find the run.


Known gaps

  • Automation failures are in the audit dump but not summarised here — records lifts them out, and the runner marks the step itself.
  • Export covers context values only; the stepContextAudit sequence is available just through the raw audit API.