Value encoding

Several conventions govern how values appear on the wire and misreading them is
the most common integration error.

Time-series sample values are strings, not numbers. Both time-series
endpoints return points as a two-element array [timestamp, value] where the
timestamp is a float epoch second rounded to one decimal place and the value is a
decimal string formatted to four places. This holds even for integer-valued
series — a session count arrives as "42.0000". This is the Prometheus wire
convention and it is preserved deliberately so query code remains portable. A
client must parse the second element.

Timestamps are epoch seconds as floats throughout the operational plane —
in events, audit entries, snapshots, and time-series ranges. The one exception is
the systemd journal reader, which passes through the journal's native
microsecond timestamps as strings on GET /api/bng/audit/journal. The
normalised audit timeline converts these to float seconds; the raw journal
endpoint does not.

Counters that originate as unsigned 64-bit integers may be serialised as
decimal strings
where they cross from the controller, so that byte counts
remain exact beyond the 2⁵³ safe-integer limit of JavaScript numbers.

Absent data is an empty string or null, consistently within an endpoint but
not across them.
The driver inventory uses "" for every unreadable field so a
client never has to null-check; the health and event surfaces use null. Read
the per-endpoint notes.