0.12.0¶
Released 2026-08-11.
The pod. A thirteenth entity type, and the first vocabulary addition since the type set became something producers import rather than retype.
No wire-contract break, no data migration. Adding a type is additive: nothing about existing types, relations or events changes.
Why a pod is not a container¶
A Kubernetes pod is the unit of scheduling and of failure: one or more containers sharing a network namespace and a lifetime. It is none of the twelve existing types — not a container, not a machine, not a service instance.
The obvious alternative was to leave it out and keep the pod's name as an
attribute on each container. It does not hold, for a reason this project has met
before: an attribute you have to string-match on is not a join. Answering
what else runs in this pod would mean scanning every container and comparing
strings — the same shape that made IP addresses untraversable until
network.address became a node of its own.
The argument that settles it is telemetry. The network namespace is shared per pod, so pod-scoped network measurements describe the pod and nothing else. A type that owns telemetry needs an entity to attach it to, or those measurements have no subject.
Secondary, and still real: the pod is the unit of failure. A node draining evicts pods, and pods take their containers with them. Without it, a blast radius reads as N containers with no grouping — which is not how anyone, human or model, reasons about a cluster.
Shape¶
| Type | pod |
| Identity | the UID Kubernetes assigns, never namespace/name |
| Relations | container → runs_on → pod → runs_on → host |
Identity is the UID for the same reason a workload's is: namespace/name is
mutable and reused, so a deployment deleted and recreated under the same name
would silently look like the same thing. The UID says otherwise.
No new relation type was needed. runs_on's From/To pairing is advisory, so
the chain composes without inventing anything, and its impact flows from target
to source — a node failing takes its pods, which take their containers,
transitively and with no extra code. impact_of answers correctly the day the
first pod arrives.
For producers¶
pod ships in pkg/emit/v0.7.0 as wire.TypePod, and Toise's registry
derives from that same constant.
Two versions matter, and they are not interchangeable:
pkg/emit/v0.7.0lets a producer compile against the type;- Toise 0.12.0 lets it emit — the boundary refuses unknown types under the default strict vocabulary, so pods sent to an older instance are rejected per-record.
That split is not an accident of packaging. The root module resolves the SDK from its published version, so a constant cannot be registered in the engine before it is tagged. It is the same ordering the vocabulary export followed.
Upgrading¶
Nothing to do. A deployment with no pods is unaffected; existing types, relations and stored events are untouched.