Signal kinds
The signal-schema v1 kind inventory (57 kinds), rendered from the SAME
exported ledger (pkg/inject/schema) the freeze tests in pkg/inject pin
(docs/signal-schema-v1.md). The schema is FROZEN: removing or renaming a kind
or a frozen field is a v2 negotiation with fleet consumers, never a
routine change;
additions are v1-additive and extend the ledger, the field pins, and the
schema doc in the same change.
Every payload carries a stable incident-class fingerprint plus
cluster/project/zone join dimensions — fleet rollup is a join, not a
parsing project. The one exception is the frozen reactive pair
(k8s-event, k8s-event-followup), whose wire shape stays
byte-identical for playbook back-compat and never gains the
identity fields.
Cross-cutting kinds
Section titled “Cross-cutting kinds”Emitted by the dispatcher itself (outcome records, storms, watchboard, triage evidence) plus the frozen reactive pair.
| Kind | Wire struct | Role |
|---|---|---|
k8s-event | Payload | Frozen reactive kind: the opening inject of a per-incident session; its wire shape is byte-identical for playbook back-compat. |
k8s-event-followup | Payload | Frozen reactive kind: a dedup-window recurrence injected into the already-open incident session. |
resolved | ResolvedPayload | Outcome record: the symptom stayed clear for —recovery-stable-for; carries resolution=recovered|object_deleted. |
resolved.reverted | ResolvedPayload | Outcome record: the symptom recurred within the revert window after a resolve. |
storm | StormPayload | Aggregate incident: opened when —storm-min incidents share a blast-radius key within —storm-window. |
storm.member | StormMemberPayload | Membership record injected into the storm session for each folded incident. |
storm.member_superseded | StormMemberPayload | Supersede pointer left in a pre-storm incident session that the storm absorbed. |
storm.update | StormUpdatePayload | Storm size refresh (latest wins): membership grew past a reporting threshold. |
watchboard.digest | WatchboardDigestPayload | Warning-class batch flushed to the shared watchboard session (—watchboard-batch / —watchboard-flush). |
watchboard.rotated | WatchboardRotatedPayload | Size-based rotation pointer naming the successor watchboard session after —watchboard-rotate digests. |
triage.regressed | TriageRegressedPayload | Regression evidence: a downgraded incident’s recurrence count reached —triage-regress-factor times its count at downgrade — evidence only, never a re-page. |
family.member | FamilyMemberPayload | Cross-source join: a signal from a different source family attached to this session’s incident (leading↔reactive) — at most one per source family per incident per dedup window; storm members never fan these out. |
sentinel.access_revoked | Payload | Coverage loss: a permission the sentinel held at startup is denied now, confirmed over consecutive SSAR sweeps — from here that source sees nothing, and its silence means less than it did. |
Source-namespaced kinds
Section titled “Source-namespaced kinds”All ride inject.Payload with the full identity stamped (source, severity, fingerprint, project, zone). The source column is the --sources name that emits the kind.
| Kind | Source | Role |
|---|---|---|
objectstate.node_notready | object-state | A Node’s Ready condition transitioned True→False/Unknown — workloads on that node are next. |
objectstate.node_flapping | object-state | A Node’s Ready condition flapped repeatedly within the flap window. |
objectstate.progress_deadline | object-state | A Deployment rollout made no progress with unready replicas — fired BEFORE the control plane’s ProgressDeadlineExceeded event. |
objectstate.endpoints_empty | object-state | A Service’s ready-endpoint count transitioned >0 → 0. |
objectstate.pdb_gridlocked | object-state | A PodDisruptionBudget’s disruptionsAllowed transitioned >0 → 0 while pods behind it exist — drains will stall. |
objectstate.restart_burst | object-state | A pod’s summed container restart count grew past the burst threshold — the leading edge of a crash loop, ahead of BackOff events. |
objectstate.node_pressure | object-state | A Node’s kubelet pressure condition (MemoryPressure/DiskPressure/PIDPressure) went False→True; escalates to critical when sustained or paired with eviction activity on the node. |
objectstate.eviction_burst | object-state | N pod evictions on one node within the burst window, folded into ONE node-scoped signal — the storm-off fallback for the per-pod Evicted event family. |
rollout.stall | rollout | A new revision made zero ready-count progress for —rollout-observe while the old revision stayed healthy. |
workload.job_failed | workload | A Job’s Failed condition went True (BackoffLimitExceeded, DeadlineExceeded, …) — batch failure with no crashlooping pod behind it. |
workload.cron_missed | workload | An unsuspended CronJob passed a scheduled activation without lastScheduleTime advancing; consecutive misses escalate to critical. |
autoscaling.hpa_pinned | autoscaling | An HPA sat at maxReplicas with its metric still over target past the sustain window — the autoscaler is out of headroom (escalates to critical when sustained longer). |
autoscaling.hpa_metrics_dead | autoscaling | An HPA’s metrics pipeline is broken (ScalingActive=False with a FailedGet* reason, sustained) — autoscaling is silently dead. |
saturation.forecast | saturation | A linear-regression forecast says a resource dimension exhausts within —saturation-warn (critical below 15m). |
degradation.capacity | degradation | A Service’s ready-endpoint ratio declined stepwise across —degradation-window — capacity eroding before the outage. |
degradation.probe_flap | degradation | A pod’s readiness gate flipped repeatedly without ever sustaining failure long enough for the reactive Unhealthy path. |
expiry.warning | expiry | An expiry countdown (certificate/token) crossed a threshold: warning at —expiry-warn, critical at the design-fixed 72h. |
capacity.pending | capacity | A NotTriggerScaleUp event: the autoscaler declined a pending pod, with per-nodegroup rejection reasons. |
capacity.scaleup | capacity | A TriggeredScaleUp event: the autoscaler asked the cloud for nodes (info; stored context for later gaps). |
capacity.scaledown | capacity | The ScaleDown event family (info; warning for ScaleDownFailed). |
capacity.scaleup_gap | capacity | A nodegroup’s cloudProviderTarget exceeded its ready count beyond the sustain window — asked for a node, didn’t get one. |
capacity.stockout | capacity | A provider scale decision names a stockout: the zone/machine-type has no capacity. Remedy-disjoint from quota. |
capacity.quota_blocked | capacity | A provider scale decision names quota exhaustion: file a quota increase. Remedy-disjoint from stockout. |
capacity.ip_exhausted | capacity | A provider scale decision names IP exhaustion: new nodes/pods cannot get addresses. |
capacity.pending-aged | capacity | A pod stayed Pending+Unschedulable past —pending-age (critical past the design-fixed 15m). |
capacity.cluster_forecast | capacity | A scheduling domain’s pod-requests/node-allocatable ratio is on a linear trend to reach 1.0 — cluster full in ~N hours, before the first pod goes Pending. |
ingress.sync_failed | ingress | An ingress-gce Warning Sync event on an Ingress: GCLB programming is failing while the Ingress object looks fine. |
ingress.translate_failed | ingress | An ingress-gce Warning Translate event on an Ingress: the spec could not be translated into GCLB resources. |
ingress.neg_failed | ingress | A NEG-controller failure on a Service (sync/attach/detach/retry): endpoints are not reaching the load balancer. |
gateway.programming_failed | gateway | A Gateway (top-level or listener) held Programmed=False past the grace window: the load balancer/data plane is not being programmed. The Gateway-API analog of ingress.sync_failed. |
gateway.route_rejected | gateway | A Gateway/listener or HTTPRoute parent held Accepted=False/ResolvedRefs=False past the grace window: the route config never became routable. The analog of ingress.translate_failed. |
quota.forecast | quota | A GCP quota’s usage slope projects exhaustion (warning ETA<7d or usage>=90%; critical ETA<48h or >=98%), with a quota-increase draft attached. |
notification.upgrade | notifications | The provider announced a control-plane or node-pool upgrade starting — store-recorded evidence for incident-window correlation. |
notification.upgrade_available | notifications | The provider offered a new version for auto-upgrade. |
notification.security_bulletin | notifications | A provider security bulletin affects this cluster — batched to the watchboard. |
token.burn | token-burn | An agent session’s token rate ran at —burn-multiple times the cross-session baseline, or projects budget exhaustion within —burn-eta. |
leeway.domain_unavailable | topology-drift | A topology domain has no node anything can be scheduled onto — the subject is the domain and not a workload, so a dead zone is one signal rather than one per workload that drifted because of it. |
leeway.contract_violated | topology-drift | A declared topology contract (a DoNotSchedule spread constraint or a required anti-affinity) is being violated, sustained past the dwell window. |
leeway.placement_drift | topology-drift | A workload’s objects deviated from the placement its intent implies — declared, inferred, or, where nobody expressed one, an even apportionment over the domains it can reach (drift ρ over threshold), sustained past the dwell window. |
leeway.baseline_breach | topology-drift | A workload that declared nothing left the placement it has held all along — a domain’s share fell outside the band around its own learned normal, sustained past the dwell window. |
leeway.rank_wedged | compute-class | Pods are Pending against a compute class that told the autoscaler not to provision outside its priority list, so no capacity of any rank will arrive without a change to the class. |
leeway.rank_degraded | compute-class | A compute class is running below the priority it prefers — too little pod-time at rank 0, or too much at the least-preferred tier, sustained past the dwell window. The pods stay Running, which is why nothing else reports it. |
leeway.rank_no_migration | compute-class | A compute class that declared it would migrate workloads back to preferred capacity has not done so since that capacity became available again. |
leeway.rank_tier_unused | compute-class | A whole preference tier has never been occupied over the observation window — a dead rung on the priority ladder, or reserved capacity being paid for and never drawn on. Info, not a page: an unused tier is frequently the intended configuration. |
Field-level detail (ordered json field lists, omitempty rules, the fingerprint recipe) lives in docs/signal-schema-v1.md.