Skip to main content

Contract-first policy decision CLI for deterministic decision + reason + trace.

Project description

Kernite

Kernite is an AI-operable policy engine for write-path enforcement. Use it as a Python library or run the OSS decision server.

It is purpose-built for one job: return a reproducible and machine-operable decision contract before any mutation call such as create, update, delete, or associate is executed.

Why Kernite

  • Reason by Design: decision reasons are structured for programmatic remediation, not only human logs.
  • Contract-First: decision, reason_codes, reasons, trace_hash are required integration surfaces.
  • Reproducible tracing: canonical input and policy context produce deterministic trace_hash output.

Design Philosophy

  • Zero overhead: no runtime dependencies (dependencies = []).
  • Zero DSL: enforce your policy without learning a new language.
  • Zero bypass: every write-mutation gets reviewed, every time.

See docs/design-philosophy.md for more information on design principles.

Compared with OPA/Cedar for AI Write Paths

Topic Kernite OPA/Cedar
Primary optimization Machine remediation in write-path gating (reason_codes support fix-and-retry loops). Human-authored policy ecosystems 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 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 governs whether a write may proceed and why.

Install and Start

uvx kernite start

If you get invalid choice: 'start', your local CLI is an older release. Use one of:

uvx --from git+https://github.com/kerniteio/kernite kernite start

or:

uv tool install --upgrade kernite
kernite start

kernite start scaffolds a starter bundle at ./kernite/.

If you want a different directory name:

uvx kernite start --dir kernite-demo

If the target directory already exists and is non-empty, use --force to overwrite.

Starter bundle files:

  • policy.json
  • execute-request.denied.json
  • execute-request.approved.json
  • guard.py
  • README.md

kernite scaffold is an alias for the same command.

Run the OSS server:

uvx kernite serve

If port 8000 is already in use:

uvx kernite serve --host 127.0.0.1 --port 8010

Run the starter flow:

cd kernite

echo "=== denied ==="
curl -sS http://127.0.0.1:8000/v1/execute \
  -H 'content-type: application/json' \
  -H 'Idempotency-Key: readme-denied-001' \
  -d @execute-request.denied.json | python -m json.tool

echo "=== approved ==="
curl -sS http://127.0.0.1:8000/v1/execute \
  -H 'content-type: application/json' \
  -H 'Idempotency-Key: readme-approved-001' \
  -d @execute-request.approved.json | python -m json.tool

If you changed --port, update curl URLs accordingly (for example http://127.0.0.1:8010).

Apply this write-path rule:

  • mutate only when data.decision == "approved"
  • when denied, branch on data.reason_codes for remediation/retry
  • persist ctx_id, data.trace_hash, data.idempotency_key

Server endpoints:

  • GET /health
  • POST /execute
  • POST /v1/execute
  • POST /validate/execute
  • POST /v1/validate/execute

/v1/execute is the versioned stability surface; /execute maps to the latest stable surface (currently v1 in this OSS server).

/execute and /v1/execute are the public decision endpoints. Each request always goes through:

  1. payload validation and normalization
  2. deterministic policy evaluation

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"]

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_hash from 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.decision enum values are only approved or denied.
  • message is human-readable (best-effort); integrations should branch on data.* fields, not message text.
  • data.reason_codes and data.reasons may be empty arrays when data.decision is approved.
  • When data.decision is denied, at least one data.reason_codes entry is present.
  • data.trace_hash is 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_codes and canonical policy-match entries used for hashing). This makes order-only differences in selected_policies/rules not change data.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 => denied with no_matching_policy
  • not governed + no selected policy => approved with out_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/parc-model.md for details and examples.

Use Cases (AI and Non-AI)

  • AI-assisted actions: gate tool calls and use reason_codes for 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/compatibility.md
  • 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/performance.md.

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

kernite-0.1.5.tar.gz (51.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kernite-0.1.5-py3-none-any.whl (23.2 kB view details)

Uploaded Python 3

File details

Details for the file kernite-0.1.5.tar.gz.

File metadata

  • Download URL: kernite-0.1.5.tar.gz
  • Upload date:
  • Size: 51.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kernite-0.1.5.tar.gz
Algorithm Hash digest
SHA256 bed5d555123863a8a2df2a5093a2c7f6c16522d7a5fa66919ffc3c7d1cdbf264
MD5 9ae7a6b921fe5861ceab0bb5fee6a7c6
BLAKE2b-256 d468e354cb45db268b1bf4960c37443a5f826b709fa669f83f4f9e1531058ee3

See more details on using hashes here.

Provenance

The following attestation bundles were made for kernite-0.1.5.tar.gz:

Publisher: release.yml on kerniteio/kernite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kernite-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: kernite-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 23.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kernite-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 780db39b41a2a5ba09a67e8ff20c07f83abd9a16e90d1944a5d865f069889686
MD5 059a86fe6a6326037513cc6b776093d0
BLAKE2b-256 446b46d86c4b3abdbec24e2d3124c2eddfe1796b620ae710c0063613e3344701

See more details on using hashes here.

Provenance

The following attestation bundles were made for kernite-0.1.5-py3-none-any.whl:

Publisher: release.yml on kerniteio/kernite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page