# kyverno-json Engine Adapter (v1.25)

The `kyverno-json` engine is Nova's **primary compliance/policy tool**
(v1.25), implemented behind the swappable `PolicyEngine` protocol so
OPA (or any other engine) can replace it one day.

## What kyverno-json is

[kyverno-json](https://github.com/kyverno/kyverno-json) is a standalone
Go binary from the Kyverno project — a **separate runtime** from the
K8s Kyverno admission controller. It applies Kyverno `ValidatingPolicy`
resources to **any** JSON or YAML payload file via the `kj scan` CLI.
Unlike the K8s Kyverno adapter (`adapters/kyverno/`), which only
speaks to K8s manifests, kyverno-json evaluates consumer contracts,
resolved Stack IR, terraform plan JSON, and even the merged PCR list
itself (meta-policies).

## Install

```bash
bash scripts/install-kyverno-json.sh
# or directly:
go install github.com/kyverno/kyverno-json/cmd/kj@latest
kj version
```

The platform functions without the binary — `is_configured()` returns
`False` when `which kj` is absent → `evaluate()` returns a single
`SKIPPED` PCR (`KJ_ENGINE_NOT_CONFIGURED`). The confidence signal
proceeds with a neutral `policy` input (D-120 graceful degradation).

## Policy directory layout

```
adapters/kyverno-json/policies/
├── _smoke.json                  # round-trip smoke test
├── contract/                    # consumer contract JSON policies
│   ├── require-id-pattern.json
│   ├── require-env-in-enum.json
│   ├── require-infrastructure-min-1.json
│   └── forbid-unknown-fields.json
├── stack-ir/                    # resolved Stack IR policies
│   ├── require-tagging-standard.json
│   ├── forbid-public-ingress.json
│   └── require-encryption-by-default.json
├── plan-json/                   # terraform show -json policies
│   ├── forbid-plaintext-secrets.json
│   ├── forbid-iam-wildcard.json
│   └── require-kms-reference.json
├── meta/                        # policies over the merged PCR list
│   ├── block-on-any-critical.json
│   └── tagging-rules-agree.json
└── regression/                   # capability-inventory policies
    ├── cap-013-adapter-dedup.json
    ├── cap-023-metrics-collector.json
    └── cap-024-deck-structure.json
```

## The four policy categories

1. **contract/** — over the consumer contract JSON (pre-resolve).
2. **stack-ir/** — over the resolved Target Stack IR (post-resolve).
3. **plan-json/** — over `terraform show -json` output (pipeline Step 5b).
4. **meta/** — over the merged `list[PolicyCheckResult]` (meta-policies).
5. **regression/** — over the capability-inventory JSON (declarative
   mirrors of `core/regression_verify.py`).

## Severity convention

kyverno-json does not natively assign severities. Each Nova policy
declares its severity via a `metadata.annotations` field:

```yaml
metadata:
  annotations:
    nova.cloudinit.dev/severity: high
```

Valid values: `critical`, `high`, `medium`, `low`, `info` (default
when absent).

## Engine enum reuse (D-116)

kyverno-json PCR records carry `engine: "kyverno"` (no new enum value).
The `engine` field records the policy-engine *family*, not the specific
binary. The K8s Kyverno adapter and the kyverno-json engine are
distinguished by `ruleId` prefix (`KYVERNO_` vs `KJ_`) and `evidence`
payload shape (`namespace`/`kind` vs `assertion`/`jmespath`).

## Schema path

The output records validate against
[`schemas/policy_check_result.schema.json`](../../schemas/policy_check_result.schema.json)
(`engine: "kyverno"` is in the enum). The confidence signal consumes
the merged PCR list engine-agnostically.

## Swap boundary

The `PolicyEngine` protocol (`core/policy_engine.py`) is the swap
boundary. The OPA-equivalent surface is documented in
`.ciagent/RESEARCH.md` §4.2 — a future `OpaEngine` implements the same
protocol without touching the confidence signal, the PCR schema, or
the pipeline.