Requirements¶
Every project requirement is a sphinx-needs req object with a stable ID.
Implementing code references these IDs from its docstrings with the :need:
role; Traceability links each one to its verifying test(s). IDs are
stable — do not renumber them.
No requirement text contains a real account value: any number below is a synthetic example.
Safety & privacy¶
The installed package imports only the Python standard library; it has zero runtime dependencies. (Design spec §4.) |
Against the trackiwi API, the only state-changing request the client
may issue is |
No private data — position cache, exported tracks, credentials — is ever committed; a pre-commit guard blocks it. (Design spec §7.2.) |
The session token is never logged or printed. Server-controlled text that can reach output (an error body a proxy may echo a header into) is redacted first. (Design spec §7.3.) |
Authentication & transport¶
The API base is taken from the login response’s |
The API base must start with |
No request follows an HTTP redirect. urllib copies the |
The |
Sync¶
Sync is offset-based and resumable: a failure never loses fetched rows and never advances the stored offset past an unstored row, so re-running continues from the highest id already stored (there is no retry loop). (Design spec §8.) |
The sync |
A page on which no line has a readable id, or a page whose highest id does not exceed the requested offset, raises rather than silently ending or looping forever. (Design spec §8.) |
The next offset is the highest id on the page, counting skipped rows whose
first field is an integer. A malformed row at the newest end of the data,
or a page of nothing but malformed rows, is skipped, counted and passed;
it never makes |
Parsing¶
A malformed field means skip-and-count the row — never crash, never store it. Non-finite coordinates and out-of-range timestamps count as malformed. (Design spec §8.) |
|
Local cache & config¶
The credentials file and the InfluxDB target config ( |
The position cache is created at mode 0600 inside a 0700 directory, and a widened mode self-heals on open. (Design spec §7.1.) |
A row with the same tracker, |
|
A locked/busy cache is distinguished from a corrupt one; the destructive
|
Export¶
|
An export covering several trackers keeps them apart: one GPX |
GeoJSON output is RFC 7946-valid: a |
|
|
Each cached row becomes one |
Heading¶
The heading helper is pure arithmetic over cached positions: no request is
made and the cache is never created by it. Moving (at or above
|
Every estimate carries a state: |
Mirror¶
The per-target mirror position advances only after InfluxDB acknowledges a batch. A failure leaves earlier batches recorded and the failed batch and everything after it for the next run. (Influx spec §5.2.) |
The only writes to InfluxDB are POSTs of |
The InfluxDB token and password never appear in output: every message built from server-controlled text is redacted first. (Influx spec §5.6.) |
A cached row always becomes the same point — same measurement, tags and timestamp — so re-sending (including a full backfill) overwrites rather than duplicates. (Influx spec §4.) |
After a successful tracker listing, |
No file under |
Every port |
The committed Grafana dashboard references its datasource only through a
|