Invarix.Gate.Evidence 1.0.0-rc.1

This is a prerelease version of Invarix.Gate.Evidence.
dotnet add package Invarix.Gate.Evidence --version 1.0.0-rc.1
                    
NuGet\Install-Package Invarix.Gate.Evidence -Version 1.0.0-rc.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Invarix.Gate.Evidence" Version="1.0.0-rc.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Invarix.Gate.Evidence" Version="1.0.0-rc.1" />
                    
Directory.Packages.props
<PackageReference Include="Invarix.Gate.Evidence" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Invarix.Gate.Evidence --version 1.0.0-rc.1
                    
#r "nuget: Invarix.Gate.Evidence, 1.0.0-rc.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Invarix.Gate.Evidence@1.0.0-rc.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Invarix.Gate.Evidence&version=1.0.0-rc.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Invarix.Gate.Evidence&version=1.0.0-rc.1&prerelease
                    
Install as a Cake Tool

Invarix.Gate.Evidence

Writes Invarix.Gate tool-call verdicts into an Invarix.Guard.Evidence decision log.

Gate decides what an agent is allowed to do. Evidence keeps an append-only record of AI decisions in CloudEvents 1.0 form. This package is the bridge: every verdict Gate renders becomes a decision record, without putting evidence I/O on the tool-call path.

Requires a commercial Gate license.

Setup

services.AddInvarixGate(gate => gate
    .Mode(GateMode.Enforce)
    .UseDefaultPack());

services.AddInvarixGuardEvidence(evidence =>
{
    evidence.AISystemId    = "support-agent";
    evidence.AISystemVersion = "3.1.0";
    evidence.ModelId       = "gpt-4o";
    evidence.ModelVersion  = "2024-11-20";
})
.UseJsonlStore("/var/evidence/decisions.jsonl");

services.AddInvarixGateEvidence();

Order matters. AddInvarixGateEvidence throws at startup if either of the other two calls is missing, and names the one to add.

The AI-system and model identity come from AddInvarixGuardEvidence and are not repeated in the bridge's options. One declaration, validated once, so the two cannot drift.

modelId on a Gate record is the agent's model, not Gate. Gate runs no model; its decision path is pattern matching. The field names the model whose tool call was judged.

The mapping

Gate Decision record
every evaluated call one record of type dk.invarix.gate.toolcall.v1
a resolved approval a second record of type dk.invarix.gate.approval.v1
tool name subject
ToolCallRequest.CanonicalArgumentsJson inputHashSha256, the exact SHA-256
no output (Gate decides before the tool runs) outputHashSha256 = SHA-256 of the empty string
each RuleFinding a detectorsFired entry: name = rule id, redactedPreview = redacted match
finding action Allow / Warn / Escalate,Deny,Terminate detector verdict pass / warn / block
nothing fired outcome: allowed
a warning outcome: allowedWithWarnings
observe mode, would have blocked outcome: allowedWithWarnings
enforce mode, denied or terminated outcome: blocked
escalated, awaiting a human outcome: blocked, oversight manualReview
approval granted outcome: overridden, oversight override
approval refused outcome: blocked, oversight reverse
operator stop-run outcome: blocked, oversight stopButton

Only the exact argument digest is recorded. Gate's loop hash is deliberately lossy: it drops volatile arguments and folds names to lowercase, so it does not commit to what actually ran. It never appears in evidence.

Escalations are resolved in GateEngine.ResolveApprovalAsync. The overload taking the call, which the shipped adapters use, notifies approval observers, this bridge among them, so the resolution is recorded with no extra wiring. A host that resolves approvals through its own machinery calls GateEvidenceBridge.OnApprovalResolved(resolved, call, decision) with the verdict it got back. Either way, an ApprovalDecision from a broker records the operator structurally; without one the outcome is recorded with no operator, which is the truthful reading of a timeout or a broken broker.

The two logs carry different things

Gate's own verdict log (docs/VERDICT-LOG.md in the Gate package) records tool arguments' hash alongside spend figures, ledger and loop state, coverage tallies, and the policy pack version. None of that reaches the evidence store.

DecisionData is sealed, has a fixed field set, no extension slot, and a wire format frozen by golden-vector tests. There is no honest place to put those values, so the bridge does not put them anywhere: nothing is encoded into a detector name, packed into a redacted preview, or appended to the subject. A record carrying a value in a field that does not mean it is not evidence, it is a decoding puzzle whose answer nobody wrote down.

The same limit costs the record the agent id, the run id, and the call id. If you need evidence searchable by run, set CorrelateByRunId = true and the run id becomes the record's correlationId instead of the ambient trace id.

An optional extensions object on DecisionData is a plausible future change to Evidence. It is not something to work around now.

Latency and loss

IGateVerdictObserver.OnVerdict is synchronous and runs while the agent waits. Mapping happens there, because it is pure CPU work and has to see the verdict as rendered. The write is queued and drained by a background task, so no tool call waits on a disk.

The queue is bounded (QueueCapacity, default 4096). When it fills, the oldest record is evicted: blocking would put evidence latency back on the tool-call path, and dropping the newest would keep the start of an incident and lose the part where it went wrong. Every eviction, failed write, and record abandoned at shutdown increments DroppedRecordCount, and the first one logs a warning. Non-zero means the log is incomplete for that process.

A write failure is logged and swallowed. A broken evidence store must not break a running agent.

Disposal stops intake and drains the queue, bounded by DrainTimeout (default 5 seconds), so a clean shutdown keeps the evidence it already produced.

Tamper evidence

Records written through this bridge are tamper-evident only when the host enables sealing with its own keys. Invarix.Guard.Evidence ships Merkle batch commitments and Ed25519 signing as an opt-in layer that you call with a key you control; AddInvarixGuardEvidence alone does not turn it on. Without sealing, a JSONL evidence file is plain text that anyone with write access can edit.

Even with sealing, the claim is bounded. In-process evidence proves that a record was not altered after it was written. It cannot prove that a compromised process wrote honest records in the first place: something that has already taken over the host can sign whatever it likes with the key that host holds. Sealing raises the cost of quiet retroactive edits. It is not proof of what happened.

License

Commercial. Contact sales@invarix.dk.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-rc.1 64 8/6/2026