Finding kinds
Every kind= the read path can emit (150 in all), rendered from the same
Kinds declarations that produce each command’s --help, MCP tool
schema, and reference page. A check cannot emit a kind that is not here:
the contract tests reject an undeclared kind, and a source sweep rejects
one no test happens to exercise.
The severity column is every level the kind can carry, worst first — one kind often spans two, because the same defect is graver in some shapes than others. A kind’s absence from a run means the check looked and found nothing (zero nominal state); it never means the check was skipped, which is reported explicitly.
These are read-path FINDING kinds. The sentinel’s wire format has its own frozen vocabulary — see Signal kinds.
| Kind | Severity | Claim | Emitted by |
|---|---|---|---|
addon.degraded | critical, warning | a kube-system add-on (dns, proxy, cni, csi, metrics, connectivity) is short of replicas; critical when none are available | bundle, health, scan, triage delta |
audit.default_sa_automount | warning | the pod runs as the namespace’s default ServiceAccount with its token automounted, and something in the pod can use it | audit hardening, scan |
audit.exemption_expired | warning | an exemption entry has lapsed: the findings it used to annotate are being reported unqualified again | audit exemptions, scan |
audit.exemption_expiring | info | an exemption entry lapses within —within — renew it or let it go deliberately | audit exemptions, scan |
audit.host_namespace | warning | the pod shares the node’s network, PID, or IPC namespace | audit hardening, scan |
audit.hostpath_mount | warning, info | the pod mounts a host path; warning when it is writable, info when read-only | audit hardening, scan |
audit.hpa_cannot_scale | warning | the autoscaler structurally cannot scale: min equals max, the target is missing, or a container has no request for its utilization target to divide by | audit workloads, scan |
audit.legacy_metadata | warning | a node pool still serves the pre-v1 instance-metadata endpoints, which any pod can read | audit cluster, scan |
audit.netpol_missing | warning, info | nothing restricts this direction for the subject — a namespace with no policy at all, or a workload the covering policies’ selectors miss; info for the egress direction, where no policy is a defensible default | audit netpol, scan |
audit.no_liveness_probe | info | a container has no liveness probe, so a wedged process is never restarted | audit workloads, scan |
audit.no_pdb | warning | the workload has no PodDisruptionBudget: a drain can take every replica at once | audit workloads, scan |
audit.no_readiness_probe | warning | a container has no readiness probe, so traffic reaches it before it can serve | audit workloads, scan |
audit.no_spread | info | the workload’s replicas are not spread across nodes or zones | audit workloads, scan |
audit.podsecurity_gaps | warning | the namespace enforces no Pod Security Admission level, so none of the above is prevented | audit hardening, scan |
audit.privileged_container | warning | a container runs privileged or holds a node-root capability (ALL, SYS_ADMIN): a container escape is a node compromise | audit hardening, scan |
audit.public_control_plane | warning, info | the control-plane endpoint is reachable from the internet; info when authorized networks narrow it | audit cluster, scan |
audit.rigid_scheduling | warning, info | placement constraints pin the workload to too few nodes to survive losing one | audit workloads, scan |
audit.single_replica | warning | the workload runs a single replica, so any disruption is an outage | audit workloads, scan |
audit.suspended_cronjob | warning | a CronJob has been suspended past —cron-suspended and has skipped activations because of it: whatever it does is not happening, and nothing else reports that | audit workloads, scan |
audit.upgrade_blocked | warning, info | an active maintenance exclusion, or a node image on the removed Docker runtime, will stop the upgrade when it comes | audit upgrades, scan |
audit.upgrade_unattended | info | upgrades will happen with nobody watching: no maintenance window, or no upgrade notifications | audit upgrades, scan |
audit.upgrade_unmanaged | warning | nothing will close that gap on its own: no release channel, or node auto-upgrade/auto-repair off | audit upgrades, scan |
audit.version_behind | warning, info | the control plane or a node pool is behind what the provider publishes, or a node pool has skewed from the control plane; info while the gap is still within the supported skew | audit upgrades, scan |
audit.workload_identity_off | warning | Workload Identity is off cluster-wide, or a node pool bypasses it — pods authenticate to the cloud as the node | audit cluster, scan |
bundle.target | info | the head record: which workload the bundle is about and which sections follow | bundle |
cert.expired | critical | a TLS secret’s certificate has expired | health |
cert.expiring | warning | a TLS secret’s certificate expires within —cert-warn | health |
cert.invalid | warning | a TLS secret’s tls.crt does not contain a parseable X.509 certificate | health |
change.config | info | a ConfigMap in the neighborhood changed | triage changes |
change.label | info | only labels changed on a neighborhood object — enough to move it in or out of a selector | triage changes |
change.node | info | a Node in the neighborhood changed | triage changes |
change.rollout | info | a workload’s pod template changed — a new image, container or mount, or a controller churn event | triage changes |
change.scale | info | a workload’s replica count changed | triage changes |
change.secret | info | a Secret in the neighborhood changed (names and shortened hashes only, never values —) | triage changes |
change.topology | info | a neighborhood object appeared, disappeared, or changed in a way none of the other classes name | triage changes |
cloud.unavailable | info | the cloud capability this check needs is unavailable, so nothing was examined — an explicit degradation record, never silence | audit cluster, audit upgrades, cloud ipspace, cloud orphans, cloud quota, cloud stockout, perf probe, scan, state wi, triage top |
crd.unavailable | info | the API group this check reads is not served by the cluster, so nothing was examined (no coverage lies) | scan, state gateway |
cron.missed | critical, warning | an unsuspended CronJob’s schedule said to run more than —cron-grace ago and status says it did not; critical once several activations in a row are gone | bundle, health, scan, triage delta |
cron.unparseable | warning | a CronJob’s spec.schedule could not be parsed, so its activations cannot be judged at all | bundle, health, scan, triage delta |
drain.bare_pod | warning | a pod on this node has no owner, so eviction deletes it permanently and nothing recreates it | stab drain |
drain.local_storage | warning | a pod on this node has emptyDir volumes: the drain needs —delete-emptydir-data and the data is lost | stab drain |
drain.node | critical, warning | the -A roll-up: this node is not cleanly drainable, with the blocker classes counted; critical when a PDB gridlock is among them | stab drain |
drain.pdb_gridlock | critical | a PodDisruptionBudget covering pods on this node allows zero disruptions: the eviction API refuses and the drain hangs | stab drain |
drain.singleton | warning | a pod on this node is the only replica of its controller — evicting it is an outage | stab drain |
drift.manual_edit | critical, warning | a manager other than the GitOps controller owns spec fields on this object; critical when one of them is high blast radius (image, replicas, env) | scan, stab drift |
edge.backend_missing | critical | an Ingress backend service, or the port it names, does not exist | bundle, scan, state edges |
edge.cert_expired | critical | a TLS certificate’s NotAfter is in the past | bundle, scan, state edges |
edge.cert_expiring | warning | a TLS certificate expires within —cert-warn | bundle, scan, state edges |
edge.cert_invalid | warning | tls.crt is missing or unparseable, or the secret is not kubernetes.io/tls | bundle, scan, state edges |
edge.endpoints_missing | critical | a selecting Service has no EndpointSlices at all | bundle, scan, state edges |
edge.endpoints_orphaned | warning | an endpoint targetRef names a pod that no longer exists | bundle, scan, state edges |
edge.endpoints_unready | critical, warning | the endpoint ready-count disagrees with the selected pods (stale or lagging slices); critical at zero ready | bundle, scan, state edges |
edge.invalid_ref | warning | the referenced object exists but is the wrong type to serve the reference | bundle, scan, state edges |
edge.missing_key | critical | the referenced key is absent from an existing ConfigMap/Secret | bundle, scan, state edges |
edge.missing_ref | critical | a referenced ConfigMap, Secret, ServiceAccount, TLS secret, IngressClass, StorageClass, or governing Service does not exist | bundle, scan, state edges |
edge.rbac_dangling | warning | a (Cluster)RoleBinding for the workload’s ServiceAccount points at a missing (Cluster)Role | bundle, scan, state edges |
edge.selector_empty | critical | a Service selector selects zero pods, so the service routes nowhere | bundle, scan, state edges |
edge.selector_unready | critical, warning | the Service selects pods but some are not Ready; critical when none are | bundle, scan, state edges |
edge.unclassed | warning | the Ingress names no class and no IngressClass declares itself the cluster default — no controller will claim it | bundle, scan, state edges |
event.hpa_thrash | warning | an HPA changed scale direction at least —hpa-flips times inside —hpa-window: the autoscaler is fighting itself | triage events |
event.normal | info | one collapsed timeline entry for a Normal-type event family — context for the warnings around it, not a problem on its own | triage events |
event.warning | warning | one collapsed timeline entry for a Warning-type event family on a subject | triage events |
findings.ack | info | the receipt for the ack this call took or cleared — what was acked, by whom, and until when | findings ack |
findings.transition | critical, warning, info | a finding subject changed state since the previous run (new|ongoing|escalated|resolved|suppressed); the severity is the underlying finding’s current one, not a judgment about the transition | findings diff |
gateway.class_not_accepted | critical | the Gateway’s GatewayClass is not Accepted by its controller | scan, state gateway |
gateway.listener_invalid | warning | one listener of an otherwise working Gateway is not resolved or not programmed | scan, state gateway |
gateway.missing_class | critical | the Gateway names a GatewayClass that does not exist — nothing will program it | scan, state gateway |
gateway.not_accepted | critical | the Gateway itself is not Accepted | scan, state gateway |
gateway.not_programmed | critical | the Gateway is Accepted but not Programmed: no data plane is carrying its traffic | scan, state gateway |
health.category | critical, warning, info | one scorecard line: how this category answered — healthy, degraded, or unavailable. The scorecard always answers, so healthy is explicit rather than silent; the line carries the worst severity found inside the category | health |
inventory.object | info | one object in scope, rendered as kubectl’s default columns for its kind — an aggregated kubectl get, so every row is emitted, healthy or not | triage list |
ipspace.range | critical, warning, info | a pod/service/node range is at 80% of its CIDR or worse; critical from 95%, info for a range the cloud APIs cannot rate and for an —all row below the line | cloud ipspace, scan |
job.failed | warning | a Job’s Failed condition is set | bundle, health, scan, triage delta |
log.fetch_error | warning | a container’s log stream could not be read, so its lines are missing from the distillation | bundle, triage logs |
log.overflow | info | the low-count tail —max-templates dropped, counted rather than discarded silently (no coverage lies) | bundle, triage logs |
log.probe_noise | info | health/readiness probe request lines stripped before distillation, counted so the removal is visible | bundle, triage logs |
log.stacktrace | critical, warning, info | a template that is a Go panic, Java exception, or Python traceback, with its innermost frames | bundle, triage logs |
log.template | critical, warning, info | one distilled template and how many lines collapsed into it; severity is the guessed level — critical at fatal, warning for error-ish, info otherwise | bundle, triage logs |
node.condition | critical, warning | a non-standard node condition is True — NPD and its cousins publish problems that way | bundle, health, scan, triage delta |
node.cordoned | warning | the node is unschedulable but still holds pods: a stuck drain or a forgotten maintenance step | bundle, health, scan, triage delta |
node.notready | critical | the node’s Ready condition is not True | bundle, health, scan, triage delta |
node.preempt | critical, warning, info | a reclaim taint marks the node for termination; severity tracks how imminent | bundle, health, scan, triage delta |
node.pressure | critical | the node reports Memory/Disk/PID pressure | bundle, health, scan, triage delta |
orphan.disk | warning | a GCE disk has been unattached for at least —min-age and is still billing | cloud orphans, scan |
orphan.lb | warning | a forwarding rule or load balancer routes to zero endpoints and is still billing | cloud orphans, scan |
pdb.gridlocked | critical, warning | the budget permits no disruptions; critical when healthy pods are already below the required minimum | bundle, health, scan, triage delta |
perf.apf_rejects | critical, warning | APF is shedding load: the apiserver is returning 429s at a priority level | perf probe, scan |
perf.apf_saturation | critical, warning | an API Priority and Fairness level is holding a sustained queue — warning from 10 queued, critical from 100 | perf probe, scan |
perf.apiserver_p99 | critical, warning | apiserver request latency p99 crossed the pack threshold for a verb/resource — warning from 1s, critical from 4s | health, perf probe, scan |
perf.etcd_db_size | critical, warning | the etcd database is approaching its quota — warning from 4 GiB, critical from 5.5 GiB | perf probe, scan |
perf.etcd_fsync | critical, warning | etcd WAL fsync p99 crossed the pack threshold — warning from 10ms, critical from 100ms | perf probe, scan |
perf.pack_unavailable | warning | a metric the requested pack needs is not in the metrics workspace, so part of the pack could not run; the rest still did (no coverage lies) | health, perf probe, scan |
perf.startup_p95 | critical, warning | pod first-ready p95 crossed the pack threshold — warning from 60s, critical from 300s | perf probe, scan |
pod.crashloop | critical | a container is crash looping | bundle, health, scan, triage delta |
pod.failed | warning | the pod reached phase Failed | bundle, health, scan, triage delta |
pod.imagepull | critical | a container cannot pull its image | bundle, health, scan, triage delta |
pod.notready | warning | a container in a Running pod has been not-ready past the —pending-age grace | bundle, health, scan, triage delta |
pod.oomkilled | warning | a container’s last termination was an OOM kill | bundle, health, scan, triage delta |
pod.pending | critical, warning | the pod has been Pending longer than —pending-age with no container-level diagnosis; critical when the scheduler has declared it Unschedulable, which is a capacity or constraint problem rather than latency | bundle, health, scan, triage delta |
pod.restarts | warning | a container has restarted at least —restarts times | bundle, health, scan, triage delta |
pod.waiting | warning | a container is stuck in an error waiting state (CreateContainerConfigError, InvalidImageName, …) | bundle, health, scan, triage delta |
probe.dns | critical, warning, info | the result of one DNS resolution: info when it resolved, warning on timeout, critical otherwise — a probe result is always emitted, success included, because the answer to “can this be reached” is the point of the command | net probe |
probe.http | critical, warning, info | the result of one HTTP GET (redirects reported, not followed): info on success, warning on timeout or 4xx, critical otherwise | net probe |
probe.tcp | critical, warning, info | the result of one TCP connect: info when it connected, warning on timeout, critical otherwise | net probe |
pvc.lost | critical | a PersistentVolumeClaim’s bound volume is lost | health |
pvc.pending | warning | a PersistentVolumeClaim is not bound; pods mounting it cannot start | health |
quota.exhausted | critical | a ResourceQuota resource is at its hard limit: the next create is rejected | bundle, health, scan, triage delta |
quota.near | warning | a ResourceQuota resource is at or past —quota-warn percent of its hard limit | bundle, health, scan, triage delta |
quota.pressure | critical, warning, info | a cloud quota is at or above —quota-warn percent of its limit; critical from 95%, info for an —all row below the line | cloud quota, scan |
radius.missing | warning | a neighbor the graph references but never observed, in a kind the snapshot does watch: the reference is dangling | bundle, triage radius |
radius.neighbor | info | one object in the target’s neighborhood, with its direction, relation, and hop distance — an enumeration of impact, not a defect | bundle, triage radius |
route.backend_port | critical | the route’s backendRef Service exists but does not expose the named port | scan, state gateway |
route.missing_backend | critical | the route’s backendRef Service does not exist | scan, state gateway |
route.missing_parent | critical | the route’s parentRef names a Gateway that does not exist | scan, state gateway |
route.not_accepted | critical | the Gateway refused the route’s attachment (listener, hostname, or namespace policy) | scan, state gateway |
scan.check_failed | warning | a stage errored; the scan continued without it, so this run saw less than a whole cluster — unless EVERY stage failed and none read anything, which is a runtime error (exit 1) rather than a scan | scan |
scan.check_skipped | info | a stage declined this invocation because a zero-argument scan cannot supply something it needs — the coverage claim is smaller than it looks | scan |
scan.incomplete | warning | the —timeout expired with stages still to run; not_run names them | scan |
spec.condition | warning | a status condition of the target that is not in its nominal state | bundle, triage spec |
spec.container | info | one container of the target: image, resources, ports, probes, env (one per container) | bundle, triage spec |
spec.resource | info | the object itself: metadata, owner, and the kind-specific highlights (one per target) | bundle, triage spec |
stockout.zone | warning | the cloud had no capacity for a machine type in this zone during the window — the reason a scale-up failed and pods stayed Pending | cloud stockout, scan |
storage.missing_class | critical | the claim names a StorageClass that does not exist — it will stay Pending forever | scan, state storage |
storage.multiple_defaults | warning | more than one StorageClass is annotated as the cluster default; which one wins is not defined | scan, state storage |
storage.no_default_class | critical | the claim names no class and the cluster has no default StorageClass | scan, state storage |
storage.no_provisioner | warning | the claim’s class is static-only (kubernetes.io/no-provisioner) and no matching PV is available | scan, state storage |
storage.pv_failed | warning | a PersistentVolume is Failed: its reclaim did not complete, so the backing disk stays allocated and the volume cannot be reused | scan, state storage |
storage.pv_released | info | a PersistentVolume is Released — retained on purpose, but its capacity is unusable until spec.claimRef is cleared | scan, state storage |
top.node | critical, warning, info | a node’s allocatable is close to committed — critical near the limit, info for an —all row below the threshold | triage top |
top.saturation | critical, warning, info | a container’s usage is close to its limit — critical near the limit, info for an —all row below the threshold | triage top |
top.unlimited | info | how many containers in scope set no cpu/memory limit, and are therefore invisible to saturation analysis | triage top |
top.unlimited_container | info | one container that sets no cpu/memory limit (—show-unlimited) | triage top |
top.unrequested | info | how many containers in scope set no cpu/memory request, so the scheduler bin-packs them as zero | triage top |
top.unrequested_container | info | one container that sets no cpu/memory request (—show-unrequested) | triage top |
triage.status | info | the triage record for an incident subject as it now stands — state, root-cause hypothesis, action, and who wrote it; a receipt, not a defect | triage status |
volume.attach_error | critical, warning | the attach or detach is failing; critical once it has been failing long enough to be stuck rather than slow | scan, state volumes |
volume.multi_attach | critical | an RWO claim is wanted by pods on more than one node — the second pod never starts | scan, state volumes |
volume.orphaned_attachment | info | a VolumeAttachment survives its PV or its node | scan, state volumes |
volume.zone_conflict | critical | the PV is locked to a zone the pod’s node is not in | scan, state volumes |
webhook.ca_expired | critical | the webhook’s caBundle has expired: the API server cannot verify it | health, scan, state webhooks |
webhook.ca_expiring | warning | the webhook’s caBundle expires within —cert-warn | health, scan, state webhooks |
webhook.dead_backend | warning | the webhook’s service backend is missing, has no ready endpoints, or does not serve the named port | health, scan, state webhooks |
webhook.failing_closed | critical | the webhook has no working backend and failurePolicy=Fail: every gated write is rejected cluster-wide | health, scan, state webhooks |
webhook.slow_risk | info | the webhook’s timeout is long enough to slow every gated write if the backend degrades | health, scan, state webhooks |
wi.gsa_missing | critical | the annotated Google service account does not exist — every GCP call from these pods fails | scan, state wi |
wi.unannotated_use | info | a pod sets GOOGLE_APPLICATION_CREDENTIALS but its ServiceAccount carries no Workload Identity annotation | scan, state wi |
wi.unbound | critical | the KSA annotates a GSA but the roles/iam.workloadIdentityUser binding is missing or malformed | scan, state wi |
workload.replicafailure | critical | the controller cannot create pods at all (quota, PodSecurity, admission) — no pod exists to diagnose | bundle, health, scan, triage delta |
workload.rollout | critical, warning | replicas are short of desired; critical when nothing is serving at all | bundle, health, scan, triage delta |
workload.stalled | critical | a Deployment’s Progressing condition is False: the rollout has given up | bundle, health, scan, triage delta |