Skip to content

Status

Status is designed before implementation on purpose, because status added afterwards reports whatever the code happened to keep rather than what an operator needs. Fixing the shape first is also a way of forcing the architecture to preserve the right information, since every field here is something a component has to be able to produce.

Proposed format

The fields are proposed. The renderings are illustrative and the layout is not settled. What the model has to contain is firmer than how it is printed.

What status answers

A single host's status answers four questions at once, and keeping them distinct is the point.

What was Datum told to do, meaning the revision and manifest it resolved. What is the host's condition now, meaning its state. What happened on the last pass, meaning when it ran, how long it took and what it changed. And how do the individual resources break down, meaning the counts by resource state.

The host status model

host
  identity        web-001

  desired
    revisionAttempted    8b91f20
    revisionApplied      8b91f20
    manifest             sha256:3f2a9c4e
    lastKnownGood        8b91f20

  state
    condition       converged
    drifted         false
    rebootRequired  false
    mode            enforce

  reconciliation
    lastAttempt     2026-02-08T09:14:22Z
    lastSuccess     2026-02-08T09:14:22Z
    duration        183ms

  resources
    total       14
    converged   14
    drifted      0
    failed       0
    blocked      0
    skipped      0
Field Meaning
desired.revisionAttempted The newest revision the last pass tried to resolve, whether or not it succeeded.
desired.revisionApplied The revision whose desired state the host is actually reconciling.
desired.manifest The digest of the effective manifest applied.
desired.lastKnownGood The newest revision that resolved and validated cleanly, per last known good.
state.condition The host state.
state.mode The reconciliation mode this host runs in.
reconciliation.lastAttempt When the last pass ran, converged or not.
reconciliation.lastSuccess When a pass last completed without failure.
resources.* Counts by resource state.

lastAttempt and lastSuccess are separate because their divergence is the signal that a host has started failing. A host whose last attempt is recent and whose last success is hours old is attempting and failing, which is a different and more urgent situation than a host that has not been attempted lately.

Divergence between desired and observed

All three revision fields being equal is the healthy case. Their divergence is how a bad commit shows up in status without needing a separate error field.

desired
  revisionAttempted  9c02ab   (failed to resolve: unknown type PackageSet)
  revisionApplied    8b91f20
  lastKnownGood      8b91f20

The host is reconciling 8b91f20, the newest commit did not resolve, and the reason is on the record. Separating attempted from applied is what makes that legible, because a single revision field has to mean one or the other and each reading loses a question somebody needs answered. Reading it across a fleet shows immediately which hosts have picked up a bad revision, which is every host the commit reached, and confirms they are still enforcing the last good state instead of sitting idle.

Fleet status

A fleet is a set of hosts, so fleet status aggregates host status and introduces nothing new.

fleet     example
revision  8b91f20

hosts     500
  converged        486
  drifted            0
  failed             3
  degraded           9
  awaiting-reboot    2
  unknown            0

behind revision      11   (last known good older than 8b91f20)

behind revision counts hosts whose last-known-good is older than the fleet's newest revision, which covers both hosts that failed to resolve a newer commit and hosts that have not yet run since it landed. Distinguishing those two requires comparing lastAttempt against the revision's age, which is detail the aggregate leaves to a per-host view.

Implementation status

Each host knows only its own status. Answering a fleet-wide question means collecting from every host, and Datum provides no mechanism for that. The model above is what a collector would aggregate, and collecting it is somebody else's job for now.

Machine-readable output

Status is consumed by other tools as well as read by people, so a structured form is required alongside the human one.

datum status --output json

Open question

The exact JSON schema is undecided, and it is one of the interfaces that becomes a contract the moment anyone automates against it. The field names above are the candidate schema, and they need settling before the first release, not after tools depend on a shape that was never designed.

What status is not

Status is a report from a host about itself, and a host reports what it observed. On a host compromised at root, that report is only as trustworthy as the host, so a fleet of converged hosts is a set of claims by those hosts and not independent evidence about them. This is the same point the threat model makes, and it bears repeating here, because a green status dashboard is exactly the thing that gets mistaken for attestation.

Status also says nothing about drift that happened after the last pass. A host reported converged at its last pass can have been edited by hand a minute later, and the report will not reflect that until the next pass observes it. Status is as fresh as the last pass and no fresher.

Relationship to metrics

Status is the authoritative local record of a host's last pass, and metrics are a numeric projection of it shaped for aggregation across a fleet.

The division is that status carries per-resource detail and metrics carry counts. A fleet of five hundred hosts with forty-seven resources each would need over twenty thousand metric series to expose what status already holds locally, which is why metrics aggregate by state and the detail is read from status on the one host that needs looking at.