Invarix.Guard.Professional
1.2.0
dotnet add package Invarix.Guard.Professional --version 1.2.0
NuGet\Install-Package Invarix.Guard.Professional -Version 1.2.0
<PackageReference Include="Invarix.Guard.Professional" Version="1.2.0" />
<PackageVersion Include="Invarix.Guard.Professional" Version="1.2.0" />
<PackageReference Include="Invarix.Guard.Professional" />
paket add Invarix.Guard.Professional --version 1.2.0
#r "nuget: Invarix.Guard.Professional, 1.2.0"
#:package Invarix.Guard.Professional@1.2.0
#addin nuget:?package=Invarix.Guard.Professional&version=1.2.0
#tool nuget:?package=Invarix.Guard.Professional&version=1.2.0
Invarix.Guard.Professional

Commercial add on for Invarix.Guard, the .NET native AI safety middleware. Runs in process with no scanner egress; your inputs never leave your box, even when your LLM call goes to OpenAI or Anthropic.
This package is license gated and requires a Professional tier license. Contact sales@invarix.dk for purchasing details, or buy directly at invarix.dk.
What it adds
The headline feature is the CustomBlocklistScanner, a license gated IScanner that lets you define rules in a JSON file your ops team can edit without redeploying. Each rule fires through two paths in parallel:
- Keyword path. Exact, predictable, fast. List the words or phrases you want flagged (e.g.
"weapons","drugs","death"); rule fires on word boundary case insensitive match. No ML lottery. - Semantic path. Embeddings catch paraphrases the keyword list can't anticipate. Rule fires when input similarity to any anchor (example or description) crosses the threshold.
Either path firing fires the rule. You can mix and match per rule: keyword only, examples only, or both.
Rules support 100+ languages out of the box. Write rules in English; matching works in Spanish, French, Chinese, Arabic, etc. with the same threshold.
Rule fields
keywords(optional): exact terms to match. Word boundary, case insensitive. Most reliable; pick concrete words you'd never want said.examples(optional): 1 to 5 short phrases describing the intent. Each is embedded individually; the scanner takes max similarity at scan time.description(optional): free text. Embedded as an additional semantic anchor.threshold(optional): cosine similarity floor for the embedding path. Default 0.82.action(required):block,warn, orlog.severity(required):low,medium,high,critical.
At least one of keywords or examples must be present.
Installation
dotnet add package Invarix.Guard.Professional
Community is a transitive dependency, so the line above is enough. For clarity:
dotnet add package Invarix.Guard
Setup
Three calls in Program.cs:
using Invarix.Guard.Extensions;
using Invarix.Guard.Professional.Extensions;
var builder = WebApplication.CreateBuilder(args);
// 1. Community: provides the engine + ML models.
builder.Services.AddInvarixGuard(o => o
.BlockInjection()
.BlockPII()
.BlockToxicContent()
.WithML(ml => ml.ModelsDirectory = "models"));
// 2. Pro license check: fails fast at startup if missing or invalid.
builder.Services.AddInvarixGuardProfessional(
licenseToken: Environment.GetEnvironmentVariable("INVARIX_GUARD_LICENSE"));
// 3. Custom blocklist: reads rules from JSON and registers as IScanner.
builder.Services.AddCustomBlocklist(o =>
{
o.ConfigPath = "config/blocklist.json";
// o.WatchForChanges = true (default) hot reloads on file save.
});
var app = builder.Build();
app.UseInvarixGuard(); // Community middleware automatically picks up the Pro scanner.
app.MapPost("/chat", (ChatRequest r) => Results.Ok(new { reply = "..." }));
app.Run();
The Pro scanner runs as part of the normal app.UseInvarixGuard() pipeline. No extra middleware glue.
Rules file
Default location: blocklist.json in the working directory. Override via CustomBlocklistOptions.ConfigPath.
Schema
{
"version": 1,
"rules": [
{
"id": "internal-codename-bluesky",
"description": "References to Project Blue Sky (internal codename, NDA only)",
"keywords": ["Blue Sky", "BlueSky", "Project Bluesky"],
"examples": [
"Project Blue Sky timeline",
"the Blue Sky launch event",
"what is codenamed Blue Sky"
],
"action": "block",
"severity": "high"
},
{
"id": "salary-disclosure",
"description": "Discussions of internal salary, compensation, or pay details",
"keywords": ["salary", "salaries", "compensation", "comp band", "pay range", "wage"],
"examples": [
"what is the salary range for senior engineers",
"how much does the VP of Sales make"
],
"action": "warn",
"severity": "medium"
},
{
"id": "competitor-strategic-mention",
"description": "Strategic mentions of named competitors. Log only, do not block.",
"keywords": ["Acme Inc", "Acme Corp"],
"examples": [
"we should beat Acme Inc on this",
"the Acme deal is at risk"
],
"action": "log",
"severity": "low"
}
]
}
Field reference
| Field | Required | Type | Notes |
|---|---|---|---|
version |
Yes | int | Currently 1. Future proofs the schema. |
rules |
Yes | array | One entry per rule. Empty array is valid (zero rules). |
rules[].id |
Yes | string | Unique within the file. Surfaced in ScanMatch.Rule as CustomBlocklist:{id}. |
rules[].description |
No | string | Free text. Also embedded as an additional semantic anchor. A tight description like "Discussions of internal salary, compensation, or pay details" gives the rule extra recall on top of the per example anchors. |
rules[].examples |
If no keywords |
array of string | 1 to 5 paraphrased examples. Each embedded as its own anchor. Empty or whitespace only entries are dropped. |
rules[].keywords |
If no examples |
array of string | Word boundary, case insensitive triggers. Fires the rule immediately when matched, no embedding compute. Most reliable path; use for terms you'd always want to catch. |
rules[].threshold |
No | float | Cosine similarity threshold for the embedding path. Default 0.82. Clamped to [0.4, 0.95]. Has no effect on the keyword path. |
rules[].action |
Yes | string | block, warn, or log. Case insensitive. |
rules[].severity |
Yes | string | low, medium, high, or critical. Case insensitive. |
Keyword matching
- Word boundary at the start of the keyword.
"pay"matches"pay","paycheck","Paypal"(start of word) but not"repay"or"display"(mid word). - Case insensitive.
"Salary"matchessalary,SALARY,SaLaRy. - Multi word keywords work.
"pay range"matches"the pay range is"cleanly. - Trade off:
"pay"matches"Paypal". If that's a problem, use a more specific keyword ("pay range","pay band") or rely on the embedding path with examples instead.
Hot reload
By default the JSON file is watched. When you save a change, the scanner reloads after a short debounce window.
- A successful reload swaps the active rule list. In flight scans always finish against the rule list they started with.
- A reload that fails (broken JSON, file removed) is logged as an error and the previous rules stay live. A typo in the editor never takes down prod.
- Disable watching for environments where the file is generated at build time and never changes:
builder.Services.AddCustomBlocklist(o => o.WatchForChanges = false);
Per rule actions
| Action | Behavior |
|---|---|
block |
Stops the request at the configured severity. The engine returns its block response and your handler is never invoked. |
warn |
Records the match but doesn't stop the request. The match shows up in GuardResult so your handler can decide what to do. Use for known noisy rules where you want signal but not action. |
log |
Logs the match to your ILogger with rule ID, similarity, and severity. No effect on the request. Use for "we want to know this is happening" rules. |
A Pro rule firing at High or Critical overrides a Community side Pass verdict, so you can use Pro rules to add policy on top of the built in scanners without touching them.
Performance
The embedding compute is shared with Community's built in scanner: there's no extra ML cost on top of what Community already pays. Adding 100 rules contributes well under 100 µs to per request latency. Memory is a few hundred KB per 100 rules.
Failure modes
| Symptom | Cause | Fix |
|---|---|---|
InvalidOperationException: AddInvarixGuardProfessional ... before AddCustomBlocklist |
Forgot to register the Pro license. | Call AddInvarixGuardProfessional(licenseToken) first. |
InvalidOperationException: AddInvarixGuard ... before AddCustomBlocklist |
Forgot to register Community. | Call AddInvarixGuard(...) first. |
InvalidOperationException: needs the multilingual embedding model |
embedding.onnx not resolvable. |
Ensure model file is in MLGuardOptions.ModelsDirectory, or enable AutoDownloadModels. |
InvalidLicenseException (any reason) |
Token missing, malformed, expired, signature failed, or wrong SKU. | Check INVARIX_GUARD_LICENSE env var or the value passed to AddInvarixGuardProfessional. |
| Rules silently not firing | Threshold too tight, examples too few or too narrow. | Review ILogger debug output; lower threshold by 0.05 or add 1 to 2 more examples. |
| Stale rules after editing JSON | WatchForChanges = false, or filesystem layer not delivering events (some Docker volume mounts). |
Either enable change watching or restart the host process. |
Lifetime + commercial terms
Professional is sold as a one time, lifetime license per company:
- All updates forever.
- Per company, unlimited environments: staging, prod, dev, internal demos.
- Non transferable on acquisition.
- No support. Not over email, chat, or GitHub Issues. The README is the only resource.
The license token is signed Ed25519 and validated fully offline against a public key baked into the package. No phone home, no licensing server. The version you bought keeps running indefinitely; it doesn't matter if Invarix shuts down.
Contact
- Commercial licensing, custom terms: sales@invarix.dk
- Security, vulnerability reports: security@invarix.dk
| Product | Versions 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. |
-
net10.0
- Invarix.Guard (>= 1.2.0)
-
net8.0
- Invarix.Guard (>= 1.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.