pycsamt.iot.provenance#
Acquisition provenance and reproducibility for IoT field sessions.
For publication and reviewer credibility, every IoT field session should be able to emit a reproducible audit trail: what was recorded, where, by whom, with which instrument, which windows were rejected, and the exact bytes of the raw files. This module builds that trail as plain JSON-able structures.
The routines are dependency-free (standard library only) and do not
import pycsamt.iot.session, so they can be reused independently.
Functions
|
Assemble an |
|
Build an acquisition manifest and write it to path. |
|
Write a manifest and per-station audits into out_dir. |
|
Write a single-station provenance audit to path (JSON). |
|
Return the hex digest of data using algo. |
|
Return a tamper-evident hash chain over entries. |
|
Return a stable hash of mapping (key-sorted JSON, UTF-8). |
|
Hash a raw acquisition file and return its integrity record. |
|
Return a normalised QC-decision record for the audit trail. |
|
Return an HMAC signature over the canonical JSON of mapping. |
|
Return whether a |
|
Verify a signed manifest produced by |
|
Return whether signature is a valid HMAC of mapping under key. |
Classes
|
Reproducible manifest describing one IoT acquisition session. |
|
Per-station occupation provenance for one field session. |
- class pycsamt.iot.provenance.ProvenanceRecord(station_id, instrument_serial=None, firmware=None, operator=None, lat=None, lon=None, elevation=None, ex_azimuth_deg=None, ey_azimuth_deg=None, occupation_start=None, occupation_end=None, sample_rate_hz=None, gps_quality=None, battery_status=None, accepted_band_hz=None, field_notes='', qc_decisions=<factory>, rejected_windows=<factory>, processing_steps=<factory>, raw_files=<factory>)[source]#
Bases:
PyCSAMTObjectPer-station occupation provenance for one field session.
- Parameters:
station_id (str)
instrument_serial (str | None)
firmware (str | None)
operator (str | None)
lat (float | None)
lon (float | None)
elevation (float | None)
ex_azimuth_deg (float | None)
ey_azimuth_deg (float | None)
occupation_start (float | None)
occupation_end (float | None)
sample_rate_hz (float | None)
gps_quality (str | None)
battery_status (str | None)
field_notes (str)
- validate()[source]#
Validate object state.
Subclasses can override this hook. The base implementation intentionally accepts all states.
- Return type:
None
- property occupation_seconds: float | None[source]#
Occupation duration in seconds, if both bounds are known.
- class pycsamt.iot.provenance.AcquisitionManifest(survey_id, created_utc=<factory>, tool='pycsamt.iot', tool_version=<factory>, method=None, operator=None, records=<factory>, devices=<factory>, files=<factory>, qc_decisions=<factory>, processing_steps=<factory>, environment=<factory>, metadata=<factory>)[source]#
Bases:
PyCSAMTObjectReproducible manifest describing one IoT acquisition session.
- Parameters:
- records: list[ProvenanceRecord]#
- validate()[source]#
Validate object state.
Subclasses can override this hook. The base implementation intentionally accepts all states.
- Return type:
None
- add_record(record)[source]#
- Parameters:
record (ProvenanceRecord | Mapping[str, Any])
- Return type:
None
- sign(key, *, algo='sha256')[source]#
Return an HMAC-signed envelope around the manifest.
The result wraps the manifest payload under
manifestalongside asignatureandsignature_algo, so it can be written out and later checked withverify_manifest()by a holder of key.
- pycsamt.iot.provenance.hash_raw_file(path, *, algo='sha256', chunk_size=1048576)[source]#
Hash a raw acquisition file and return its integrity record.
Returns a mapping with
path,bytes,algo,digest, andmodified_utc. RaisesFileNotFoundErrorwhen the file is missing.
- pycsamt.iot.provenance.hash_bytes(data, *, algo='sha256')[source]#
Return the hex digest of data using algo.
- pycsamt.iot.provenance.hash_mapping(mapping, *, algo='sha256')[source]#
Return a stable hash of mapping (key-sorted JSON, UTF-8).
- pycsamt.iot.provenance.sign_mapping(mapping, key, *, algo='sha256')[source]#
Return an HMAC signature over the canonical JSON of mapping.
Unlike
hash_mapping(), which anyone can recompute, an HMAC signature also proves the manifest was produced by a party holding the shared key – useful for asserting a field audit trail has not been tampered with in transit.
- pycsamt.iot.provenance.verify_signature(mapping, signature, key, *, algo='sha256')[source]#
Return whether signature is a valid HMAC of mapping under key.
Uses a constant-time comparison so verification does not leak timing information.
- pycsamt.iot.provenance.verify_manifest(signed, key)[source]#
Verify a signed manifest produced by
AcquisitionManifest.sign().Checks the HMAC signature over the wrapped
manifestpayload and, when present, that the payload’s owncontent_hashstill matches.
- pycsamt.iot.provenance.hash_chain(entries, *, algo='sha256', genesis='')[source]#
Return a tamper-evident hash chain over entries.
Each returned entry is a copy of the input with
seq,prev_hash, andentry_hashadded, whereentry_hashfolds in the previous entry’s hash. Altering, inserting, or reordering any entry breaks the chain from that point on (detected byverify_hash_chain()). This suits a running log such as per-window QC decisions.
- pycsamt.iot.provenance.verify_hash_chain(chained, *, algo='sha256', genesis='')[source]#
Return whether a
hash_chain()sequence is intact and in order.
- pycsamt.iot.provenance.log_qc_decision(station, decision, *, channel=None, reasons=None, operator=None, timestamp=None, window=None)[source]#
Return a normalised QC-decision record for the audit trail.
- pycsamt.iot.provenance.build_acquisition_manifest(survey_id, *, records=None, devices=None, qc_decisions=None, processing_steps=None, method=None, operator=None, metadata=None)[source]#
Assemble an
AcquisitionManifestfrom session components.- Parameters:
- Return type:
- pycsamt.iot.provenance.export_acquisition_manifest(survey_id, path, *, indent=2, **kwargs)[source]#
Build an acquisition manifest and write it to path.
Thin convenience over
build_acquisition_manifest()+AcquisitionManifest.write();kwargsare forwarded to the builder (records,devices,qc_decisions,method, …). Returns the written path.
- pycsamt.iot.provenance.export_station_audit(record, path, *, indent=2)[source]#
Write a single-station provenance audit to path (JSON).
- pycsamt.iot.provenance.export_reproducibility_bundle(manifest, out_dir, *, include_raw=False, zip_bundle=False)[source]#
Write a manifest and per-station audits into out_dir.
- Parameters:
manifest (AcquisitionManifest) – The session manifest to export.
out_dir (str) – Destination directory (created if needed).
include_raw (bool) – When
True, copy referenced raw files intoout_dir/rawif they exist on disk.zip_bundle (bool) – When
True, also produce<out_dir>.zipof the bundle.
- Returns:
Paths written:
manifest,audits, optionalrawandzip.- Return type: