Skip to main content

Draft a Policy from Observation

Task

Most security tools ask you to write the policy. AIControls watches a discovered workload and drafts one for you. Use this for an image you did not build, a vendor container, or anything in a cluster you inherited.

Self-managed installations only

Workload Trust is available only in private, self-managed AIControls installations, on premises or in a cloud cluster that you run. It needs a dedicated cluster that you run, with Kyverno, Kyverno Runtime, and cluster OIDC and RBAC access in place. Nirmata-hosted (SaaS) workspaces don't include it. See Feature availability.

What the draft is, and what it is not​

The draft is a RuntimePolicy: a network allow list, a file allow list, and an executable allow list, assembled from what the sensor observed the workload actually doing.

Three things it is deliberately not:

  • It is not a bill of materials. Which frameworks, models, and libraries are inside a workload comes from scanning its code. Watching it run tells you what it connected to, what it opened, and what it executed — and nothing about what is linked into the binary doing it.
  • It is not signed by AIControls. The draft carries the provenance aicontrols-observed, its observation window, and its per-pod coverage. Signing our own observation would be circular, and you need to see exactly what you are accepting.
  • It is not a registration. The draft records what the workload did, not what it is supposed to do. Registration remains Discovered until a user creates a workload record — see Register a workload.

Draft a policy​

  1. Open Inventory → Workloads.
  2. Find the workload, open its detail drawer, expand Activity, and under Observed behavior, select Draft policy….
  3. Read the banner. It states, on every draft, that adopting the policy grants no trust.
  4. Work down the drawer: the observation gates, then each drafted behavior, then what the draft could not see.
  5. Copy the YAML and apply it yourself. AIControls never applies a draft for you.

The policy you apply is yours, not an AIControls-managed object: it carries no managed-by label, so nothing in AIControls adopts, rewrites, or deletes it.

The observation gates​

A policy drafted from twenty minutes of a nightly batch workload is wrong, and the failure mode is a broken production workload the first time you enforce it. So the draft is gated, and a failed gate is shown with the measurement and the threshold both named.

GatePasses when
Observation windowThe window is at least 24 hours.
Pod coverageAt least 80% of the workload's pods produced evidence. A pod that did nothing and a pod nothing watched look identical from here, so the silent pods are named.
Scheduled workload firedA CronJob or Job produced evidence inside the window. AIControls does not read the schedule, so it cannot tell a job that did nothing from one that never ran — a warning, not a block.
Evidence completeThe whole window was read, rather than a truncated page of it.
Ingest lagEvery observation the sensor counted reached the database. Counters that were never read report unknown, which is not the same as clean.
Observation planeEvery drafted behavior's evidence could be collected at all.

When a blocking gate fails the draft still renders — reading it is how you find out what is missing — but it is marked unfit to adopt.

Read the evidence on every line​

Expand any drafted value to see the observations that produced it: what was seen, how many times, which observation policy reported it, and when it was last seen. A line you cannot interrogate is a line you will approve without reading.

Two labels matter more than the rest.

Observed versus resolved​

A destination the workload connected to and a name it merely resolved are different facts, and the draft tags them differently.

A line drafted from a DNS question may permit a destination the workload never reached. Worse in the other direction: a workload that reaches a cached answer, a hardcoded address, or a name resolved over DoH or DoT asks no question at all, so its destination never appears. Treat a Resolved only line as a hint to confirm, not as a fact.

Complete source versus filtered source​

The network observation reports every IPv4 connection, so a network list drafted from it is a complete record of the window.

The file and executable observations do not. Both are narrowed by detection filters — they report AI-SDK, model-file and credential-file access, and agent-CLI and MCP-server execution — so a list drafted from them holds a small subset of what the workload really does.

Never enforce a file or executable list drafted from observation. Those filters are permanent, so no observation window ever completes those lists. In Observing, the same list is useful because everything outside it gets reported. The drawer marks these lists Observation only.

A network list can also report Not ready for enforcement, which is usually fixable. If network observation was not running, every drafted line rests on a DNS question instead of an observed connection. Enable network observation and draft again.

What the draft cannot see​

Every draft ends with its own coverage gaps, stated rather than left as a silent absence:

  • IPv6 egress. AIControls compiles no IPv6 network value, so IPv6 destinations are never drafted. With kyverno-runtime v0.1.3 or earlier, an allow list that omits an IPv6 destination doesn't deny it. With v0.1.4 or later, the version the chart bundles, the enforced rule's default deny blocks every IPv6 destination, and nothing in the draft can allow one back. See #3452.
  • File and executable evidence with no open/exec hooks. Where no node has the open/exec hooks, that whole class of evidence is structurally unavailable — a different fact from "none was seen", and never rendered as a clean result.
  • Component inventory. See above: observation cannot produce one.

What enabling a drafted policy would and would not do​

The draft always renders in Observing. Enabling enforcement is a separate action after you review what would be blocked — see Enable enforcement for a workload.

Even then, the enforcement is narrower than the value lists suggest:

  • exec matches the executed binary only, never its arguments. A workload permitted to run a shell may run anything through it.
  • open has no read/write distinction. One value list means a path you allowed for writing is readable too.
  • network carries no ports at the kernel plane, and matches a domain from the pod's own cleartext DNS answer or from Service informers. There is no SNI.
  • dns cannot enforce at all, which is why there is no drafted DNS behavior. The names a workload resolved feed the network draft as weaker evidence instead.

Enabling a drafted policy does not create a registration or directly set Verification. Verified remains derived from active, holding enforcement.

Pre-fill the intent declaration​

The drawer also offers the models and MCP servers the gateway saw this workload use, so whoever fills in the intent form does not have to remember them.

These are a suggestion — accept, edit, or reject them. AIControls asserts none of it, nothing is stored until you submit the form, and a form nobody submitted declares nothing.

Two limits worth reading:

  • Purpose and autonomy are left blank on purpose. They are statements about what the workload is for, and no amount of watching converts "it called a model 400 times" into "its purpose is drafting customer replies, with a person approving each one."
  • Only traffic that reached the gateway appears. A model called directly, bypassing the gateway, is absent here — which is itself worth knowing.

Next steps​