Files
harmony/harmony_types
Jean-Gabriel Gill-Couture 0d01a71cd5
All checks were successful
Run Check Script / check (pull_request) Successful in 2m8s
feat(iot-contracts): type AgentStatus fields with Id + DateTime<Utc>
`AgentStatus.device_id` and `AgentStatus.timestamp` were stringly
typed. Both now carry real types that prevent a whole class of
wire-format typos while keeping the on-wire JSON shape intact.

**device_id: String → harmony_types:🆔:Id**

Agent config + heartbeat payload now share the same `Id` that the
example IoT pipeline already uses for `IotDeviceSetupConfig`. Mixing
a device id with a deployment name or arbitrary `String` is now a
type error. `Id` is re-exported from `iot-contracts` so consumers
don't need a direct `harmony_types` dependency just to name the
field.

To keep the wire format byte-compatible, `harmony_types::Id` gains
`#[serde(transparent)]`. Audit: no consumer in the tree relies on
the previous `{"value": "…"}` shape — `Id` is persisted by sqlite
via `to_string()`, never serialized directly — so this is a
latent-bug fix more than a behavior change.

**timestamp: String → chrono::DateTime<Utc>**

The agent was calling `chrono::Utc::now().to_rfc3339()` and stuffing
the String into the payload. It now holds a real `DateTime<Utc>`
which serde-serializes as RFC 3339 anyway. The smoke script's
reboot-gate lex comparison still works: time-digit prefixes resolve
before the trailing `Z` (chrono default) vs `+00:00` (prior format)
difference matters.

**Plumbing**

- `iot/iot-agent-v0/src/config.rs`: `AgentSection.device_id: Id`.
  TOML deserializes the bare string thanks to `#[serde(transparent)]`.
- `iot/iot-agent-v0/src/main.rs`: `watch_desired_state` and
  `report_status` take `Id` instead of `String`.
- `iot/iot-contracts/Cargo.toml`: adds `harmony_types` path dep and
  `chrono = { workspace, features = ["serde"] }`.

**Verification**

- `cargo test -p iot-contracts`: 8/8 passes. New assertions pin the
  wire format: `"device_id":"pi-01"` (not `{"value":"pi-01"}`) and
  `"timestamp":"2026-04-21T18:15:42Z"` (RFC 3339).
- x86_64 smoke-a3.sh PASSes end-to-end including the reboot-
  reconnect loop — wire format remains compatible with the existing
  smoke-script parsing.
2026-04-21 15:12:11 -04:00
..