mod annotations;
mod backend;
mod config;
mod measurement;
mod protocol;
mod replicates;
mod status;
mod streams;
mod vocabulary;
pub use annotations::{AnnotationMapping, AnnotationUpsert, NoteMapping, NoteUpsert};
pub use backend::{
DeclinedChannel, SourceCandidate, SourceInventory, SourceWindow, StreamDescriptor,
StreamFetchRequest, StreamReadings, StreamStatusEvents,
};
pub use config::RunnerConfig;
pub use measurement::MeasurementType;
pub use protocol::{
CommandUpdateRequest, EnrollRequest, EnrollResponse, HeartbeatRequest, HeartbeatResponse,
PendingCommand, SyncEventCreate, SyncEventRef, SyncEventUpdate, SyncResult, SyncTrigger,
};
pub use replicates::{
ColumnAssignment, CurveMapping, GroupAudit, ReplicateSpec, SensorUpsert, StandardCurveUpsert,
};
pub use status::{CommandStatus, ServiceStatus, SyncEventStatus, SyncEventType};
pub use streams::{DataStream, IngestReading, IngestStatusEvent, RegisterStreamRequest};
pub use vocabulary::UnknownValue;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_shapes_that_refuse_an_unknown_field() {
fn refuses<D: serde::de::DeserializeOwned>(mut json: serde_json::Value) -> bool {
json["a_field_the_sender_gained"] = serde_json::json!(1);
serde_json::from_value::<D>(json).is_err()
}
assert!(refuses::<IngestReading>(serde_json::json!({
"time": "2026-01-15T10:00:00Z", "raw_value": 1.0
})));
assert!(refuses::<IngestStatusEvent>(serde_json::json!({
"time": "2026-01-15T10:00:00Z", "value": "unreachable"
})));
assert!(refuses::<SourceWindow>(serde_json::json!({
"from": "2026-01-01T00:00:00Z", "to": "2026-02-01T00:00:00Z", "source_rows_read": 1
})));
assert!(refuses::<GroupAudit>(serde_json::json!({
"time": "2026-01-15T10:00:00Z"
})));
assert!(refuses::<SensorUpsert>(serde_json::json!({
"source_key": "sensor_inventory:62", "name": "DOC corr", "is_lab_instrument": true
})));
assert!(refuses::<AnnotationUpsert>(serde_json::json!({
"source_key": "annotations:9",
"stream_id": "00000000-0000-0000-0000-000000000006",
"time": "2026-01-15T10:00:00Z", "category": "audit", "text": "x"
})));
assert!(refuses::<NoteUpsert>(serde_json::json!({
"source_key": "notes:1", "site_name": "FP1", "text": "x", "verified": true
})));
assert!(!refuses::<RegisterStreamRequest>(serde_json::json!({
"source_system": "cnet", "source_key": "FP1:DOC",
"source_name": null, "source_path": null, "metadata": {}
})));
assert!(!refuses::<StandardCurveUpsert>(serde_json::json!({
"source_key": "standard_curves:17", "instrument_label": "DOC corr",
"slope": 1.0, "intercept": 0.0
})));
assert!(!refuses::<ColumnAssignment>(serde_json::json!({
"column": "DOC_A", "index": 0
})));
}
#[test]
fn the_fields_the_api_accepts_travel() {
let instrument = SensorUpsert {
source_key: "sensor_inventory:62".to_string(),
name: "DOC corr".to_string(),
serial_number: None,
manufacturer: None,
model: None,
notes: None,
is_lab_instrument: true,
data_frequency: Some("low".to_string()),
metadata: None,
};
let json = serde_json::to_value(&instrument).unwrap();
assert_eq!(json["data_frequency"], "low");
let curve = StandardCurveUpsert {
source_key: "standard_curves:17".to_string(),
instrument_label: "DOC corr".to_string(),
slope: 1.0,
intercept: 0.0,
r_squared: None,
name: None,
fitted_on: None,
notes: Some("re-fitted after the lamp change".to_string()),
};
let json = serde_json::to_value(&curve).unwrap();
assert_eq!(json["notes"], "re-fitted after the lamp change");
let event = IngestStatusEvent {
time: chrono::Utc::now(),
value: "unreachable".to_string(),
sensor_id: Some(uuid::Uuid::nil()),
};
let json = serde_json::to_value(&event).unwrap();
assert_eq!(json["sensor_id"], uuid::Uuid::nil().to_string());
}
#[test]
fn an_undeclared_field_is_not_sent() {
let instrument = SensorUpsert {
source_key: "sensor_inventory:62".to_string(),
name: "DOC corr".to_string(),
serial_number: None,
manufacturer: None,
model: None,
notes: None,
is_lab_instrument: false,
data_frequency: None,
metadata: None,
};
let json = serde_json::to_value(&instrument).unwrap();
assert!(json.get("data_frequency").is_none());
let event = IngestStatusEvent {
time: chrono::Utc::now(),
value: "ok".to_string(),
sensor_id: None,
};
let json = serde_json::to_value(&event).unwrap();
assert!(json.get("sensor_id").is_none());
}
}