Safety

How kprompt gates cluster mutations: prompt-level hard denies, plan risk levels, explicit approval, and tighten-only org policy.

Safety features reduce risk; they do not make kprompt safe for unattended production use. The product is experimental. Always review the plan. Skip --approve until you understand the proposed actions.

Every mutating plan is risk-evaluated before apply. On a TTY, kprompt asks y/N unless you pass --approve. Read-only intents (get, list, explain, investigate, why, timeline, impact, audit, cleanup, search, score, architecture, learn, drift, logs, describe, performance, trace, dashboard, optimize, graph, Istio traffic, GitOps status) do not require approval.

Where the checks run

The pipeline is prompt → intent → plan → safety → approval → executor → Kubernetes. Safety runs at two distinct points, which is why some prompts never reach the model at all.

StageWhat it checksEffect
Prompt checkDestructive natural-language patternsDenied before any LLM call — no token spend
Plan evaluationActions, resource kinds, names, integration rulesAssigns risk or denies the plan outright
Org policy overlayCached Team policy, when enrolledMay only tighten the local verdict
ApprovalTTY confirmation or explicit --approveLast gate before the executor runs

Hard denies

Some prompts are refused by pattern before the model is called: wiping or destroying the cluster, deleting everything or all namespaces, and deleting a namespace by name. These are cheap, deterministic refusals rather than a judgement call left to the LLM.

Refused before any LLM spend

$ kprompt "delete everything in the cluster"
🚨 Intent: destructive cluster operation
🛡️ Safe execution: denied
😅 Your cluster lives another day

Next: kprompt "delete deployment <name>" -n <namespace>

Wipe-class denials rotate a small flavor pack of punchlines (stable per prompt) and always append a Next remediation line with a named-target example. The punchline is branding; the Next line is the teachable path.

Plan-level ruleWhy
Delete must target Pod, Deployment, or ServiceAny other kind is refused rather than guessed at
Delete must name one resourceNames like *, all, everything, or --all are refused as unscoped
Delete without a resource kind is refusedAn ambiguous target is never resolved for you
Namespace deletion is always refusedBlast radius is too large for a compiled plan

Example plan-level deny

kprompt "delete all pods in production"
# Risk: denied — name a single resource

Risk levels

Plans surface one of four verdicts. Denied plans never apply. Medium and high plans still need explicit approval — risk is information for your review, not permission to skip it.

RiskTypical intentsApproval
lowReads, explain, investigate, learn, drift, optimize reports, service graphs, GitOps statusNone required
mediumScale, deploy, install, upgrade, rollback, patch, workflows, Tekton, KEDA, GitOps syncTTY y/N or --approve
highNamed deletes, Crossplane cloud claims, unrecognised intentsExplicit approval; Crossplane needs strong approval
deniedHard-deny prompts and unsafe plansNever applies

learn and drift are RiskLow (read-only scans). Optional approve-gated GitOps sync follow-ups from drift are separate KindGitOps plans at medium risk. If an older CLI treated drift as high, upgrade — org max_risk=medium would incorrectly deny those scans.

Integration-specific rules layer on top for Helm, Argo Workflows, Tekton, KEDA, Istio, Crossplane, and GitOps, so a risky chart install or a cloud claim is not treated as a generic mutation. Multi-tool mutating routes produce one aggregate plan and a single approval rather than a chain of prompts.

Diffs and blast radius

When a live object already exists, plans include a before→after diff so you review the actual change rather than only the intent summary. That is the difference between approving "scale api to 10" as a sentence and approving it as a concrete replica change on a named Deployment.

Multiple clusters

Fan-out is deliberately asymmetric: reads and optimize rollups can span contexts freely, while mutations cannot be approved for many clusters by accident. --approve never implies cross-context apply; you confirm each context or pass --approve-each-context explicitly. Setting require_alias_match true refuses a mutation unless your kubectl current-context matches the alias you targeted.

Org policy (when enrolled)

A cached Team policy can only tighten local rules — it never loosens a local hard deny. Pull it with kprompt policy pull and inspect it with kprompt policy.

Policy fieldEffect
max_riskDenies any plan whose risk exceeds low, medium, or high
deny_intentsDenies named intents outright
allow_namespacesRestricts plans to an allowlist of namespaces
deny_namespacesDenies plans targeting listed namespaces
require_approveForces approval for medium risk and above

Example org deny (max_risk=medium vs a high plan)

kprompt policy
# max_risk: medium
kprompt "delete deployment redis" -n payments
# 🛡️ Org policy max_risk is medium — plan risk high exceeds it

When enrolled, each plan also best-effort pushes a planned, denied, or applied audit event to the control plane. Disable it with KPROMPT_DISABLE_AUDIT=1.

What safety does not do

  • It does not verify that a plan is correct — only that it is not obviously destructive
  • It does not replace kubeconfig RBAC; kprompt can only do what your credentials allow
  • It does not redact Secret values from reads you are already authorised to perform
  • It does not make --approve in CI equivalent to human review
  • It does not cover generic mutation of arbitrary resource kinds, which stays out of scope

Treat the safety engine as a floor, not a ceiling. The honest limits, including what Autopilot will and will not do, are documented on the roadmap.