Skip to content

audit

UTC traceability evidence: a per-sample error bound, windows, coverage and an archivable report.

Regulated users (e.g. MiFID II RTS 25: 100 us / 1 ms to UTC; DORA and NIS2 for trustworthy logs) need a bound, not just an offset. For each sample::

bound = |offset| + path + upstream + reference

path how wrong the offset can be because the network path is asymmetric: half the round-trip delay when the log has it (the worst case is all delay in one direction), else asymmetry given by the user, else 0 (reported as an assumption). upstream how far the source itself can be from its reference: root_delay / 2 + root_dispersion when the log has them (chrony, the ntpstats monitor, NTP/NTS servers), else the peer dispersion (ntpd peerstats), else upstream given by the user, else 0. reference the uncertainty of the top of the chain against UTC (e.g. of a GNSS receiver or UTC(k)), given by the user.

Time is cut into windows (1 h by default). A sample covers the time until the next sample, but at most max_gap median intervals; the rest is unmonitored and never counts as compliant. A window fails when any bound exceeds the limit, and is insufficient when its coverage is below min_coverage.

The report states every assumption it applied, and carries the tool version and SHA-256 hashes of the inputs, so it can be archived and reproduced. It describes measurements; interpreting a regulation is up to its user.

components(s, cfg)

Per-sample bound terms and the rules that produced them.

audit(s, cfg, events=None)

Audit one series; returns a JSON-serialisable dict.

public(result)

The result without the plotting arrays.