Ninka.Authz 0.7.0

dotnet add package Ninka.Authz --version 0.7.0
                    
NuGet\Install-Package Ninka.Authz -Version 0.7.0
                    
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="Ninka.Authz" Version="0.7.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ninka.Authz" Version="0.7.0" />
                    
Directory.Packages.props
<PackageReference Include="Ninka.Authz" />
                    
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 Ninka.Authz --version 0.7.0
                    
#r "nuget: Ninka.Authz, 0.7.0"
                    
#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 Ninka.Authz@0.7.0
                    
#: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=Ninka.Authz&version=0.7.0
                    
Install as a Cake Addin
#tool nuget:?package=Ninka.Authz&version=0.7.0
                    
Install as a Cake Tool

Ninka.Authz

The .NET runtime for Ninka. It loads Ninka runtime bundles and evaluates their OPA WASM in-process — no network or policy server on the request path. The package targets net8.0 and pins its Wasmtime dependency.

Install

dotnet add package Ninka.Authz

Generate the C# Consumer Projection

A .NET application integrates through one generated file that it commits — the C# Consumer Projection:

npx ninka-authz build --out-csharp Generated/Ninka.g.cs

The file carries the execution bundle inside it, so there is no artifact directory to deploy and none to read at run time. --out-csharp names the file itself: C# has no source-root convention to resolve one from. (compile accepts the same flag; build additionally fails when the pinned OPA toolchain is unavailable.)

Each policy's input contract is a record named i_<hash> — a policy id is data and is never turned into an identifier — with a <Pascal>Input alias beside it for the ids that produce a unique one, and a Policy reference on the record itself.

Usage

using Ninka.Generated;

using var authz = NinkaProjection.Create();

bool allowed = authz.Check(InvoiceAccessInput.Policy, new InvoiceAccessInput { /* … */ });
if (!allowed)
{
    // deny
}

An application that keeps its artifacts as files instead loads the directory:

using var authz = Authz.Load("ninka/out");

Authz.Load verifies bundle identity/integrity/compatibility before a policy can serve a decision. It does not read source Tegata, so it does not determine whether a newer Tegata exists in the source tree.

Authz.Check accepts the generated PolicyRef<T> and compares its tegata_hash with the loaded manifest before evaluation. Mixing generated C# from one compile with a bundle from another therefore fails instead of evaluating under the wrong generated contract.

Check returns bool (true = ALLOW, false = DENY) and is thread-safe; evaluations are serialized per loaded policy.

Acquiring a bundle

A bundle reaches this runtime by one of two paths, and they converge on one implementation of what is accepted and what is refused:

  • Authz.Load(dir) — reads a directory of artifacts. This is how an application, a script or a test harness loads artifacts that exist as files.
  • Authz.FromEmbedded(bundles) — reads the artifacts a generated Consumer Projection carries (EmbeddedBundle: the build record, the manifests, and the module as base64). It is the low-level entry that generated code hands its bundle to, not a second authorization API to call directly.

They differ in how the bytes arrive and in nothing else: the same artifact is refused for the same reason, with the same message, either way.

Load-time checks

The implementation verifies, among other runtime-bundle invariants:

  • bundle id / filename consistency;
  • module bytes against build.json.wasm_sha256;
  • manifest presence and policy identity, per binding;
  • a supported artifact_format_version on both the build record and every manifest — artifact v2 has no compatibility mode, so a version-less artifact is refused;
  • manifest.rego_sha256 == binding.rego_sha256 lineage;
  • the entrypoint the artifacts DECLARE: the binding and the policy's manifest must name the same one, and the module must really export it. The entrypoint is compiler-derived artifact data — this runtime never derives it from a policy id;
  • OPA-WASM compatibility, including the no-host-builtins contract;
  • uniqueness of loaded policy ids, within a bundle and across bundles.

One broken link refuses the whole bundle, not the affected policy: a bundle is a single execution artifact, and serving the rest from bytes whose provenance is partly unaccounted for would be the fail-open the checks exist to prevent.

Failures throw NinkaLoadException rather than producing ALLOW.

Decision log

Off by default. When enabled, each Check emits one entry following the OPA Decision Log field model where ARTIFACT_SPEC §5.6 defines the semantics as equivalent. Ninka-specific semantics and the known deviations are documented separately — field-name overlap alone does not imply semantic equivalence, so the format is not plainly "OPA-compatible". The entry's input is the evaluation input projected onto the declared AuthzInput shape (subject.properties, action.name, resource.type, resource.properties, context) and then masked. A value appears raw from two sources, and only two: the attributes the manifest lists under decision_log.unmasked (the vocabulary's own declaration), and action.name / resource.type, which are always raw — they are call-site literals rather than runtime data, and they are never listed under decision_log.unmasked. Every other value keeps its key and becomes "***"; unlisted means masked. Keys outside the projected shape are omitted from the entry rather than masked in it — nothing in the entry records the omission. A throwing sink is observation-only and does not change the decision.

An entry's field set is not closed: a consumer must tolerate fields this contract does not name and must not reject or drop an entry because it carries one. Compatible fields may be added without changing ninka.schema or artifact_format_version.

var authz = Authz.Load("ninka/out", decisionLog: new DecisionLogOptions { Enable = true });

macOS trap handling

Ninka configures Wasmtime to use POSIX-signal trap handling on macOS. Wasmtime permits one trap handling method per process. If an application also creates a default Mach-port-configured Wasmtime Engine, the incompatible configuration panics; configure other engines with macos_use_mach_ports = false when they must coexist.

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 was computed.  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
0.7.0 195 8/20/2026
0.6.1 125 8/19/2026
0.5.0 108 8/13/2026
0.4.1 115 8/12/2026
0.4.0 105 8/11/2026
0.3.5 96 8/11/2026
0.3.4 106 8/11/2026
0.3.3 94 8/10/2026
0.3.2 97 8/10/2026
0.3.1 98 8/10/2026
0.3.0 100 8/10/2026
0.2.15 113 8/9/2026
0.2.14 106 8/9/2026
0.2.13 105 8/8/2026
0.2.12 99 8/8/2026
0.2.11 100 8/8/2026
0.2.10 99 8/8/2026
0.2.9 102 8/8/2026
0.2.8 101 8/8/2026
0.2.7 112 8/7/2026
Loading failed