Verified: Publishing to MQTT (Sparkplug B)
Each claim the Publishing to MQTT (Sparkplug B) page makes, with the tests that
prove it in the last green CI run: 23 of 25 verified.
The claims live in docs/claims/sparkplug.yaml.
Last green CI run 16 Oct 2026, 14:48 UTC on c7618d3 · all runtime claims
SPB-001 verified
The node's birth certificate (NBIRTH) lists the whole tag store with names, types and current values, and each tag's `unit:` and `desc:` arrive as the `engUnit` and `documentation` metric properties, including on template members.
SPB-002 verified
Types map faithfully: BOOL to Boolean, integers to Int64, REAL to Double, UDT to Template.
SPB-003 verified
A host can write the tags `writable:` names back via NCMD: a scalar command overwrites the tag in the store for the program to act on.
SPB-005 verified
`Node Control/Rebirth` is honored: the node answers the command with a fresh NBIRTH.
SPB-006 verified
Only `broker` and `group-id` are required.
- pass
TestSparkplugConfigininternal/project - pass
TestSparkplugOnlyBrokerAndGroupIDAreRequiredininternal/project
SPB-007 verified
The password is never read from the manifest: it comes from `NAUTILUS_MQTT_PASSWORD`.
- pass
TestSparkplugPasswordComesFromTheEnvironmentininternal/project(3 of 3 passed)
SPB-008 verified
`ssl://host:8883` brokers connect over TLS.
- pass
TestEdgeNodeConnectsOverTLSinsparkplug
SPB-009 verified
`edge-node` defaults to the project name.
- pass
TestSparkplugEdgeNodeDefaultsToTheProjectNameininternal/project
SPB-010 verified
`deadband` publishes a numeric only when it moved more than that in absolute units; zero publishes on any change.
- pass
TestRBEDeadbandAndHeartbeatinsparkplug - pass
TestRBEZeroDeadbandPublishesAnyChangeinsparkplug - pass
TestRBEDeadbandOnStructMembersinsparkplug - pass
TestRBEDeadbandOnNestedStructinsparkplug - pass
TestSparkplugManifestClassesReachTheNodeininternal/project
SPB-011 verified
`min-interval` means never publishing more often than that, even on change.
- pass
TestRBEDeadbandAndHeartbeatinsparkplug - pass
TestRBEMinIntervalStillAppliesToStructsinsparkplug - pass
TestSparkplugManifestClassesReachTheNodeininternal/project
SPB-012 verified
`max-interval` publishes at least that often even when the value is unchanged (heartbeat).
- pass
TestRBEDeadbandAndHeartbeatinsparkplug - pass
TestShouldPublishSampleGenerationinsparkplug - pass
TestSparkplugManifestClassesReachTheNodeininternal/project
SPB-013 verified
`every-change: true` publishes every transition unconditionally, ignoring deadband and rate limits, while an unchanged sample stays quiet.
- pass
TestRBEDisableAndBoolChangeinsparkplug - pass
TestSparkplugManifestClassesReachTheNodeininternal/project
SPB-014 verified
`metric-classes` assigns tags to a named class by glob, and every tag unassigned uses `default-class`.
- pass
TestClassResolutioninsparkplug
SPB-015 partly verified
Every field connection publishes as its own Sparkplug device under the edge node, carrying the input tags it delivers (its `__Online` companion included); computed tags, program state, outputs and every tag of the `memory` loopback publish at node level.
- pass
TestMetricsSplitBetweenDevicesAndTheNodeinsparkplug - pass
TestSparkplugDevicePerConnectionininternal/project - pass
TestSparkplugMemoryMakesNoDeviceininternal/project
SPB-016 verified
A device's DBIRTH/DDEATH follow its connection's health: when one link drops the host sees that device die rather than stale values, while every other device stays born.
SPB-017 verified
With `primary-host` set, the node defers its birth until the host's STATE is ONLINE, and both the 2.x (plain ONLINE/OFFLINE) and 3.0 (JSON) STATE encodings are accepted. By default (`primary-host-offline: buffer`), when the host goes offline the node stays connected and born (no NDEATH) and stops publishing data, which is buffered and replayed as historical with store-forward and not sent without it.
- pass
TestParseStateinsparkplug - pass
TestPrimaryHostDefersTheBirthUntilOnlineinsparkplug(3 of 3 passed) - pass
TestNoPrimaryHostBirthsOnConnectinsparkplug - pass
TestStoreForwardBuffersWhileThePrimaryHostIsOfflineinsparkplug - pass
TestPrimaryHostOfflineWithoutStoreForwardSendsNothinginsparkplug - pass
TestPrimaryHostOfflineDefaultKeepsTheSessioninsparkplug
SPB-026 verified
With `primary-host-offline: disconnect`, when the host goes offline the node publishes NDEATH (the ending session's bdSeq) before a clean disconnect, connects again with the next bdSeq, and births only once the host is ONLINE again; with store-forward it buffers meanwhile and replays as historical after the new birth. An offline STATE older than the last online one is ignored. The key needs `primary-host`.
- pass
TestPrimaryHostOfflineDisconnectEndsTheSessioninsparkplug - pass
TestHostOfflineDisconnectDoesNotBirthWhileTheHostIsOfflineinsparkplug - pass
TestSparkplugPrimaryHostOfflineininternal/project
SPB-018 verified
With `store-forward: N`, data messages are buffered while the broker is unreachable (or the primary host is offline) and replayed, marked historical, once delivery resumes.
- pass
TestStoreForwardBuffersAcrossABrokerOutageinsparkplug - pass
TestBrokerDropStartsANewSessionWithTheNextBdSeqinsparkplug - pass
TestStoreForwardBuffersWhileThePrimaryHostIsOfflineinsparkplug - pass
TestNoPublishWhileTheConnectionIsNotOpeninsparkplug - pass
TestTimedOutTickIsBufferedWhenStoreForwardIsOninsparkplug
SPB-019 verified
The store-and-forward buffer is a bounded ring that drops the oldest record when full, and the drain is rate-limited.
SPB-028 verified
With `store-forward-file`, the store-and-forward buffer is journaled to that file as it fills, so a process exit during an outage does not lose it: the next start loads it and replays it, marked historical and with its original timestamps, after the first birth (whether the outage was the broker or the primary host, in either `primary-host-offline` mode), then clears the file. The file is bounded like the ring; a torn last record is skipped with a log line and an unreadable file is set aside. Without the key nothing is written to disk.
- pass
TestStoreForwardFileSurvivesARestartDuringABrokerOutageinsparkplug - pass
TestStoreForwardFileSurvivesARestartDuringAHostOutageinsparkplug(3 of 3 passed) - pass
TestStoreForwardFileRoundTripinsparkplug - pass
TestStoreForwardFileIsBoundedLikeTheRinginsparkplug - pass
TestStoreForwardFileSkipsATornLastRecordinsparkplug - pass
TestStoreForwardFileSetsAnUnreadableFileAsideinsparkplug - pass
TestStoreForwardFileMisconfigurationinsparkplug - pass
TestStoreForwardWithoutAFileTouchesNoDiskinsparkplug - pass
TestSparkplugStoreForwardFileininternal/project
SPB-022 verified
`bdseq-file` persists the birth-death sequence number across restarts; without it bdSeq restarts at 0 each run.
- pass
TestBdSeqFilePersistsAcrossRestartsinsparkplug
SPB-027 verified
A dropped broker connection is a new session: the broker's will carries the old bdSeq, and the node reconnects with the next bdSeq, persisted to `bdseq-file`, in both its new will and its new NBIRTH, so a host applies the next death and ignores a late will from the old connection. Commands, the primary host's STATE and store-and-forward carry on across the reconnect.
- pass
TestBrokerDropStartsANewSessionWithTheNextBdSeqinsparkplug - pass
TestBrokerDropResubscribesToThePrimaryHostinsparkplug - pass
TestBrokerDropThenHostOfflineDisconnectinsparkplug - pass
TestEdgeBrokerDropIsANewSessionToTheHostinsparkplug/host
SPB-023 verified
The node passes the Sparkplug TCK edge-node profile, run against a live node on every push.
- pass
TestTCKConformanceinsparkplug
SPB-024 verified
MQTT and protobuf live only in the sparkplug package; the runtime core's one dependency outside the Go standard library is gopkg.in/yaml.v3.
SPB-025 partly verified
`driver: {type: sparkplug-host}` presents an edge-node group as input tags in a central project, with writes going back as NCMD/DCMD.
- pass
TestLoadSparkplugHostDriverininternal/project - pass
TestTCKHostConformanceinsparkplug/host