Contract-first policy decision CLI for deterministic decision + reason + trace.
Project description
Kernite
Kernite is a policy engine to make your APIs LLM-ready.
It scans API schema, generates initial policy, and returns a reproducible decision contract with AI-operable reasons.
Unlike other general policy engines such as Casbin/OPA/Cedar, Kernite is purpose-built for making APIs policy-enforceable and ready for programmatic remediation with AI agents.
Why Kernite
- Developer-friendly: scan API schema, generates policy, and apply them to endpoints in 60 seconds.
- Reason by Design: decision reasons are structured for programmatic remediation, not only human logs.
- Contract-First:
decision,reason_codes,reasons,trace_hashare required integration surfaces. - Reproducible tracing: canonical input and policy context produce deterministic
trace_hashoutput.
Design Philosophy
- Zero overhead: no runtime dependencies (
dependencies = []). - Zero DSL: enforce your policy without learning a new language.
- Zero bypass: every write-mutation gets checked by
kernite check.
When should I use this?
Use Kernite if:
- Your API surface is large and you want policy coverage visibility from OpenAPI.
- You want machine-operable deny reasons for automated remediation and retry.
- You need deterministic evidence (
trace_hash) that you can persist and replay.
Use Casbin/OPA/Cedar if:
- You want a mature policy language ecosystem with centralized governance tooling.
- You already have an established policy pipeline and need a dedicated PDP.
Comparisons with other policy engines
| Topic | Kernite | Casbin/OPA/Cedar |
|---|---|---|
| Primary goal | Policy-gate API for AI operations and remediations (fix-and-retry with reason_codes). |
Human-authored policy enforcement and policy-language tooling. |
| Decision contract | Required structured contract (decision, reason_codes, reasons, trace_hash). |
Explanations exist, but the remediation contract is not standardized across integrations (codes/reasons/evidence vary by setup). |
| Reproducible evidence | Built-in deterministic evidence surface (trace_hash) plus conformance vectors for replay. |
Strong policy engines; replay determinism depends on integration and policy/data pipeline discipline. |
While Casbin/OPA/Cedar/others are strong options for centralized policy-language workflows, Kernite is purpose-built for app-embedded, machine-operable, write-path enforcement with a stable response contract.
Non-goals
- A general-purpose policy language / DSL runtime.
- Proxying or routing traffic (Kernite returns decisions; your app performs the write).
- Replacing your domain logic. Kernite decides and explains; your app enforces.
Install and Scan First
uv tool install kernite
Start from your API project repo and run a strict coverage scan before wiring enforcement.
Example project used here:
https://github.com/fastapi/full-stack-fastapi-template
git clone https://github.com/fastapi/full-stack-fastapi-template.git
cd full-stack-fastapi-template/backend
uv sync
Export OpenAPI JSON from the app code:
mkdir -p .kernite
uv run python -c 'import json; from pathlib import Path; from app.main import app; Path(".kernite/openapi.json").write_text(json.dumps(app.openapi(), indent=2), encoding="utf-8")'
Run strict scan and write a machine-readable report:
kernite check \
--schema .kernite/openapi.json \
--report-out .kernite/kernite-check.strict.json || true
Inspect what needs to be addressed:
jq '.summary' .kernite/kernite-check.strict.json
jq '.violations[:10] | map({code, method, path, field})' .kernite/kernite-check.strict.json
From a real run on the template above (2026-02-23), strict scan reported:
write_operations = 17violations = 34- top remediation codes:
missing_x_kernite,missing_policy_key
This is the intended first checkpoint for large API surfaces: identify uncovered write operations before you enforce.
OpenAPI Policy Generate and Check
Input format for v1 is OpenAPI JSON only. YAML files are intentionally rejected with conversion guidance to keep the core runtime dependency-free.
Generate bundle + mapping + report:
kernite policy generate \
--schema ./openapi.json \
--out-dir ./.kernite
Generated artifacts:
policy-bundle.generated.jsonpolicy-map.generated.jsonpolicy-generation-report.json
Check coverage (strict by default):
kernite check \
--schema ./openapi.json \
--mapping ./.kernite/policy-map.generated.json \
--bundle ./.kernite/policy-bundle.generated.json \
--report-out ./kernite-check-report.json
Exit codes:
0valid coverage1coverage violations (strict)2input/parse errors
Library Quick Start (Python)
from kernite import evaluate_execute
request = {
"workspace_id": "workspace-demo",
"principal": {"type": "token", "id": "api:ops-bot"},
"object_type": "document",
"operation": "create",
"payload": {"title": "Q1 Plan"},
}
result = evaluate_execute(request, idempotency_key="req-001")
decision = result["data"]["decision"]
trace_hash = result["data"]["trace_hash"] # persist with your write/audit record
reason_codes = result["data"]["reason_codes"]
Embedded Runtime Modes (Enforce / Observe / Skip)
Use evaluate_execute_controlled(...) when you want staged rollout and built-in sink emission.
from kernite import ObservabilityConfig, evaluate_execute_controlled
config = ObservabilityConfig.from_env()
sink = config.create_sink()
result = evaluate_execute_controlled(
request,
idempotency_key="req-001",
mode=config.mode,
sink=sink,
sink_failure_policy=config.sink_failure_policy,
)
if result["allow_write"]:
# proceed with mutation
pass
Environment defaults:
KERNITE_MODE=enforce|observe|skip(defaultenforce)KERNITE_SINK=none|jsonl|csv|sqlite(defaultnone)KERNITE_SINK_PATH=/path/to/file_or_db(required when sink enabled)KERNITE_SINK_FAIL_POLICY=fail_open|fail_closed(defaultfail_open)
Production Notes (OSS Reference Server)
- Authentication/authorization: the OSS reference server does not include built-in authn/authz. Run it behind your trusted boundary (for example mTLS, JWT verification, internal network policy, or API gateway auth).
- Request size/timeouts: the OSS reference server does not define built-in max body size or per-request timeout controls. Enforce size limits and timeouts at ingress/runtime (reverse proxy, gateway, or process supervisor).
- Logging/metrics: the OSS reference server is minimal by design (startup log only, request access logs suppressed by default). Add structured logs/metrics in your service wrapper or edge layer, and persist
ctx_id/trace_hashfrom responses for audit evidence.
Quick Start: Execute
Request (governed scope with one policy, missing required title):
In v1, an allow policy is approved only if all its rules pass; any rule failure produces a denied decision with structured reasons.
{
"workspace_id": "workspace-demo",
"principal": {
"type": "token",
"id": "api:ops-bot"
},
"object_type": "document",
"operation": "create",
"payload": {},
"policy_context": {
"governed": true,
"selected_policies": [
{
"policy_key": "document_create_default",
"policy_version": 1,
"effect": "allow",
"rules": [
{
"rule_key": "require_title",
"rule_definition": {
"type": "required_fields",
"fields": ["title"]
},
"reason_code": "missing_required_fields",
"reason_message": "title is required."
}
]
}
]
}
}
Response shape:
{
"ctx_id": "ctx_...",
"message": "Denied by governance policy.",
"data": {
"decision": "denied",
"reason_codes": ["missing_required_fields"],
"reasons": [
{
"code": "missing_required_fields",
"message": "title is required.",
"rule_key": "require_title",
"field_path": "payload.title",
"details": {
"missing_fields": ["title"]
}
}
],
"policy_selection_reason_code": "policy_selected_workspace_default",
"policy": {
"policy_key": "document_create_default",
"policy_version": 1
},
"trace_hash": "sha256:...",
"idempotency_key": "..."
}
}
Happy-path response example (approved):
{
"ctx_id": "ctx_...",
"message": "Approved by governance policy.",
"data": {
"decision": "approved",
"reason_codes": [],
"reasons": [],
"policy_selection_reason_code": "policy_selected_workspace_default",
"policy": {
"policy_key": "document_create_default",
"policy_version": 1
},
"trace_hash": "sha256:...",
"idempotency_key": "..."
}
}
Contract invariants (v1):
- Required response fields:
ctx_id,message,data,data.decision,data.reason_codes,data.reasons,data.policy_selection_reason_code,data.policy,data.trace_hash,data.idempotency_key. data.decisionenum values are onlyapprovedordenied.messageis human-readable (best-effort); integrations should branch ondata.*fields, not message text.data.reason_codesanddata.reasonsmay be empty arrays whendata.decisionisapproved.- When
data.decisionisdenied, at least onedata.reason_codesentry is present. data.trace_hashis stable across v1.x for the same canonicalized input and policy context.- Canonicalization rule: Kernite deterministically canonicalizes all hash-participating arrays (for example sorted
reason_codesand canonical policy-match entries used for hashing). This makes order-only differences inselected_policies/rulesnot changedata.trace_hash.
Policy Context Model
policy_context is optional, but recommended for production integrations.
Kernite evaluates the policies you provide in policy_context.selected_policies; in OSS mode it does not fetch policies from storage.
Main fields:
governed(bool): whether this request must be enforced as governed scope.selected_policies(array): policies selected by your resolver.governed_scopes(array): optional scope list (object_type+operation) to infer governed status.policy_selection_reason_code(string): explicit selection reason, if already known.
Default behavior:
- governed + no selected policy =>
deniedwithno_matching_policy - not governed + no selected policy =>
approvedwithout_of_scope_phase1
PARC Request Model
Kernite uses a Cedar-style PARC shape:
- principal
- action (
operation) - resource
- context
This keeps policy evaluation explicit and stable for relationship operations like associate.
See docs/concepts/parc-model.mdx for details and examples.
Use Cases (AI and Non-AI)
- AI-assisted actions: gate tool calls and use
reason_codesfor automatic retry/remediation. - Internal APIs: apply one deterministic write guard across UI/API/workers.
- SaaS multi-tenant systems: enforce tenant-scoped write decisions and persist evidence.
See docs/use-cases.md for details and examples.
Compatibility and Conformance
- Contract policy:
docs/concepts/compatibility.mdx - Conformance vectors:
docs/conformance/v1/execute_vectors.json - Reason code semantics:
docs/conformance/v1/reason_codes_v1.json
Objective Performance Check (Python)
Kernite includes a dependency-free benchmark harness.
uv run python benchmarks/benchmark_execute.py --iterations 20000
This gives p50/p95 latency and throughput from your actual environment so language/runtime decisions are based on measured data.
Latest measured snapshot is tracked in docs/concepts/performance.mdx.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kernite-0.1.6.tar.gz.
File metadata
- Download URL: kernite-0.1.6.tar.gz
- Upload date:
- Size: 72.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0182d9615604958dab9753e2404ce148d11685c694b7c22c40723cc052047067
|
|
| MD5 |
0110668e28f59f04f66c474795d86f80
|
|
| BLAKE2b-256 |
d0a1272c71d793008c955264a97fc67a2865ebf40dd4ebd4a72d35a5818722bc
|
Provenance
The following attestation bundles were made for kernite-0.1.6.tar.gz:
Publisher:
release.yml on kerniteio/kernite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kernite-0.1.6.tar.gz -
Subject digest:
0182d9615604958dab9753e2404ce148d11685c694b7c22c40723cc052047067 - Sigstore transparency entry: 981938880
- Sigstore integration time:
-
Permalink:
kerniteio/kernite@032219c6ba351895cc9c6fb9cc4bb86214feafcf -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/kerniteio
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@032219c6ba351895cc9c6fb9cc4bb86214feafcf -
Trigger Event:
push
-
Statement type:
File details
Details for the file kernite-0.1.6-py3-none-any.whl.
File metadata
- Download URL: kernite-0.1.6-py3-none-any.whl
- Upload date:
- Size: 37.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
412886d91f75d1a5ac32c52d9de5aa75ea70c0cfe962eae84f53ed4b47f60a0a
|
|
| MD5 |
4666a99fc75be64f69b673bfa4fbb3b3
|
|
| BLAKE2b-256 |
70499d52eb65eafef59988eb01b27ebeb57daa2b33043b13ef56feec709cd250
|
Provenance
The following attestation bundles were made for kernite-0.1.6-py3-none-any.whl:
Publisher:
release.yml on kerniteio/kernite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kernite-0.1.6-py3-none-any.whl -
Subject digest:
412886d91f75d1a5ac32c52d9de5aa75ea70c0cfe962eae84f53ed4b47f60a0a - Sigstore transparency entry: 981938928
- Sigstore integration time:
-
Permalink:
kerniteio/kernite@032219c6ba351895cc9c6fb9cc4bb86214feafcf -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/kerniteio
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@032219c6ba351895cc9c6fb9cc4bb86214feafcf -
Trigger Event:
push
-
Statement type: