Package Information
Available Nodes
Documentation generating…
Documentation
n8n-nodes-truveil
A Truveil audit node for n8n. One node, six operations: register the agent,
log an action, log a decision, request an approval, request a
consequential-decision checkpoint, and check run readiness — a read-only ask
of whether the run's audit record is complete enough to be graded, which
names what is missing instead of leaving you to find out from a report.
Status
This is 0.3.0 (adds Check Run Readiness to 0.2.0). Which version the
registry serves is a question this file cannot answer without going stale, so
it does not try. One command answers it:
npm view n8n-nodes-truveil version
If that prints 0.1.2, you are looking at the defective version. 0.1.2 was
published 2026-08-05 and has the ten defects listed under "What 0.2.0 fixes".
The worst of them means no run logged through it can be graded at all: 0.1.2
never typed an event and never sent a step ordinal, so every audit comes backinsufficiently_instrumented while every call returns ok. Upgrade as soon as
0.2.0 is on the registry.
This section is written as a question-and-a-command rather than as a claim for a
specific reason. The README shipped inside 0.1.2 said, in this spot, "Not
published to the n8n community registry. Pending a reviewed working local
install." That was true when written and false by the time it was published, and
it is why nobody remembered the package was live for 46 days. npm always ships
the README whatever the files field says, so this is the section a stranger
reads, and a snapshot of publication state is the one thing it must not contain.tests/n8n_node_contract.test.js enforces that: it fails if this section
asserts a publication state instead of pointing at the registry.
Install
In n8n: Settings, Community Nodes, Install, then enter n8n-nodes-truveil. That
installs whatever the registry currently serves — see Status above.
Create a Truveil API credential with your per-user API key, which the node
sends as the x-client-secret header. The endpoint defaults tohttps://mcp.truveil.app/mcp.
Then read the next section before you build anything. The shape of the
workflow decides whether your run can be graded at all, and the most common way
to get an ungradable run is to skip one step.
LOCAL_TEST.md and docker-compose.yml cover running it against a local n8n.
The workflow this is built for
One step decides whether your run can be graded. A run with no event typed
ingestionevidences nothing at all in Data Trust, and a grade that presents
itself as describing four dimensions is withheld when a record can only speak
to three. The audit comes backinsufficiently_instrumentedeven if every
other field is filled and your coverage is above the threshold. That is the
engine refusing to overstate what your logs support, not the node failing.Step 2 below is that step. Put a Log Action with Event Type
ingestion
straight after the node that reads your data, and Data Trust has something to
stand on.
Measured end to end by test_n8n_node_earnings.py at the repository root. Six
steps, and the order matters:
- Register Agent — fill Intended Purpose and Owner Email. They are the only
evidence for two signals, and a blank field is now omitted rather than
written over what you registered last time. - Log Action, Event Type ingestion — right after the node that reads
your data. This is where provenance is credited. - Log Decision — the classification, with Sources filled in if it cited
anything.Autotypes itsynthesis, which is where citations count. - Request Approval — records the request. It does not record a human
answer; Truveil never sees one. - Log Decision, Human Checkpoint on — after the approval, once a
person has actually decided. It inherits the approval handle from step 4
automatically, which is what links the request to the decision. - Log Action — the send, with AI Disclosure Text if the output carried one.
- Check Run Readiness — at the end. Read-only: it writes nothing and
returns no grade.truveil.readinessandtruveil.summaryon the item say
whether the record clears the grading floor, and each floor condition still
in force names exactly what clears it. One node at the end of the flow, not
one after every write.
Measured on that workflow, engine 2.0.0 / bible-2.0, category 1:
| scenario | signals earned | coverage | status |
|---|---|---|---|
| every field left at its default | A3 T6 | 8.70% | insufficiently_instrumented |
| four operations, every field filled | A1 A3 R2 T1 T2 T3 T4 T6 | 34.78% | insufficiently_instrumented |
| the six steps above | A1 A3 A4 A5 D1 R2 T1 T2 T3 T4 T6 | 45.83% | graded, 46.2, D |
Two of those rows are worth reading carefully.
A run with everything left at its default earns two signals and is refused a
grade. That is correct, not a defect: nothing was stated, so there is nothing to
grade, and the only way to a grade would be to put back exactly what defect 10
removed.
The middle row clears the 33.33% coverage threshold and is still floored, on a
structural condition: Data Trust is empty. D2 went with the hardcoded
freshness_check, and D1 is credited only on an event actually typed ingestion,
which a four-step workflow has no step for. That is the price of not
manufacturing a signal, and it is why step 2 above exists.
What it does
Auto-derived from the execution context, because n8n genuinely holds these:
- run_id — the n8n execution id, so every Truveil call in one run groups
together on the dashboard. - step — each Truveil node reads the step the upstream Truveil node put on
the item and adds one, so the run is ordered 1, 2, 3 without anyone typing it.
Overridable, and the override is ignored unless it parses as an integer. - action — derived from the upstream node when left blank, and never
inherited from a Truveil node's own name. - data_provenance —
[{source, fetched_at, version}], wheresourceis the
upstream node andfetched_at/versioncome from the item itself. Omitted
rather than invented when the item carries neither. - event_type —
Autotypes a decision assynthesis, and an action asdisclosurewhen it carries disclosure text, otherwiseoutput. It never
guessesingestion: that is the one type the node cannot tell from outside. - JSON-RPC envelope,
run_idplacement insidearguments, SSE de-framing and
serialization, all internal tosrc/transport.ts.
You supply the judgments n8n cannot infer: risk, reversibility, oversight mode,
human checkpoint, AI disclosure text, the sources you actually cited, and the
event type when Auto would be wrong.
The node makes no claim on your behalf. It does not assert that data was checked
for freshness, does not cite the upstream node's name as a source, and does not
stamp the current clock as a fetch time. Those are things the audit is about, so
they are yours to state.
Fail-soft by construction: the node catches its own errors, surfaces them on its
own output (json.truveil.ok = false with json.truveil.error), and never
throws into the host workflow.
What 0.2.0 fixes
All ten defects measured at S9-IB-1, each pinned bytest_n8n_node_earnings.py.
- No
event_typeon any call.sourcesanddata_provenanceare read
only on a typed row, so both were stored and neither credited. Now every
logging call is typed. → T4, D1 - No
stepon any call. T6 (workflow_trace) is scored on step. The node
counts now. → T6 - The run could not be graded. Consequence of 1 and 2. The documented
workflow is graded. oversight_mode: 'none'was offered and is outside the server's enum, so
the call was rejected and fail-soft hid it. Replaced withhuman_on_loop.approval_idwas unreachable. It sat on Log Action, whose schema does not
declare it, so it was stripped. It is on Log Decision now, inherited
automatically, and lands on bothapproval_idandcheckpoint_ref. → A5human_checkpointwas inert on both operations that offered it, for the
same reason. It is on Log Decision only. → A4risk,reversibleandhuman_checkpointon Request Approval were sent
and stripped: the gate declares none of them. Removed from that operation.jurisdictionwas free text against a closed nine-value server enum.
Now a dropdown.intended_purposeandowner_emailwere sent as empty strings, so a
re-registration overwrote stored values. Blank fields are omitted.freshness_check: truewas hardcoded. Removed, not moved to a field: a
node asserting a check nobody performed is manufacturing a signal its user
never claimed. D2 is now unevidenced unless a deployer states it through
another path, which is the honest reading.
Two related changes not in the numbered list, both the same principle as 10:sources is no longer derived from the upstream node's name (it is asked for),
and fetched_at is no longer filled from the current clock when the item has no
timestamp (it is omitted).
Layout
src/ TypeScript sources — the source of truth
dist/ compiled output, tracked (see below); what package.json ships
scripts/ build asset copy, the offline args test, the live harness
Build
npm install
npm run build # rimraf dist && tsc && node scripts/copy-assets.js
npm test # 63 offline unit checks, no n8n and no network
Why dist is in the repository
package.json declares files: ["dist"], so dist/ is exactly what npm
publishes. Tracking it means three things the repo needs:
- what the registry serves can be diffed against HEAD without a build;
test_n8n_node_earnings.pyandtests/n8n_node_contract.test.jsload the
node directly, sonpm testat the repository root needs nonpm install
here and no TypeScript;- the contract guard pins every tracked file's digest, so a source change
committed without a rebuild fails, and — when TypeScript is installed in this
directory — rebuilds fromsrc/and asserts the output is byte-identical.
Without TypeScript that limb skips, which is the same posture the repository
takes for pytest and for the live schema-drift guard.
Fix bugs in src/, run npm run build, and commit both.