Ninka.Authz
0.7.0
dotnet add package Ninka.Authz --version 0.7.0
NuGet\Install-Package Ninka.Authz -Version 0.7.0
<PackageReference Include="Ninka.Authz" Version="0.7.0" />
<PackageVersion Include="Ninka.Authz" Version="0.7.0" />
<PackageReference Include="Ninka.Authz" />
paket add Ninka.Authz --version 0.7.0
#r "nuget: Ninka.Authz, 0.7.0"
#:package Ninka.Authz@0.7.0
#addin nuget:?package=Ninka.Authz&version=0.7.0
#tool nuget:?package=Ninka.Authz&version=0.7.0
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_versionon 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_sha256lineage;- 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.
Links
- Documentation: https://docs.ninka.dev
- Source: https://github.com/AranSeshita/ninka-authz (
runtimes/dotnet) - License: BUSL-1.1
| 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 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. |
-
net8.0
- Wasmtime (= 44.0.0)
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 |