Commit graph

48 commits

Author SHA1 Message Date
David Kiania
274473c544 docs: update analytics report with live DB state (18 Apr 2026)
Some checks failed
Static Analysis / static (push) Waiting to run
Tests / test (push) Waiting to run
Static Analysis / static (pull_request) Has been cancelled
Tests / test (pull_request) Has been cancelled
- §1: add current deployment state table — 63 devices, 0 driver names,
  5 trips, pipeline stopped 6 Apr (401 token expiry); note tracksolid_2
  vs tracksolid schema split
- §6: status column per question (Ready/Needs data/Blocked) reflecting
  actual DB state; add cost-per-ticket, city drift, odometer rows
- §8: add Step 0 full deployment sequence (git pull → migrations 01-06
  → container rebuild → sync_driver_audit → import_drivers_csv);
  Step 3 updated to reference import script; Step 5 collapsed to pointer
- Footer: db-state stamp and update date

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 08:39:58 +03:00
David Kiania
cebcf74ba2 feat: business analytics expansion + driver CSV import
- 01_BusinessAnalytics.md: add §0 usage tags, §2.4 cost-per-ticket,
  §3.6–3.8 alarm/drift/odometer, §4.4–4.5 dispatch log + SLA metrics,
  §9 fleet readiness scorecard, §10 service-interval forecaster,
  Appendix B threshold calibration guide (773 → 1437 lines)

- 06_business_analytics_migration.sql: schema support for all new
  analytics sections — assigned_city column, dispatch_log table,
  ops schema, service_log, odometer_readings, tickets skeleton,
  vw_service_forecast view

- import_drivers_csv.py: one-shot script to populate driver_name,
  vehicle_number, vehicle_models, cost_centre, assigned_city, sim,
  iccid, imsi from 20260414_FS__Logistics - final_fixed.csv (144 rows);
  dry-run by default, --apply to commit, --only-null for safe additive mode

- 20260414_FS__Logistics - final_fixed.csv: source data committed for
  reproducibility and container exec workflow

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 08:30:34 +03:00
David Kiania
8867be9d3d perf+fix: SAVEPOINT-per-item pollers, batched GPS inserts, parallel detail fetch
Some checks are pending
Static Analysis / static (push) Waiting to run
Tests / test (push) Waiting to run
Audit fixes across the ingestion stack:

Observability
- Move log_ingestion out of batch loops in poll_alarms and poll_parking
  (was emitting N cumulative log rows per run instead of one).
- Add missing log_ingestion + t0 to poll_trips.
- Count inserted via cur.rowcount instead of naive +=1 so ON CONFLICT
  DO NOTHING no longer inflates the metric.

Resilience
- SAVEPOINT-per-item added to poll_alarms, poll_live_positions,
  poll_trips, poll_parking so one bad row no longer aborts the batch
  (webhook handlers already had this; pollers were inconsistent).

Performance
- /pushgps and poll_track_list now use psycopg2.extras.execute_values
  with ON CONFLICT DO NOTHING — 10-50x write throughput on larger
  batches.
- sync_devices and sync_driver_audit fetch jimi.track.device.detail
  concurrently via ThreadPoolExecutor(max_workers=8), cutting the
  daily registry sync from ~24s to ~3s for an 80-device fleet.
- poll_track_list split into two phases: parallel API fetch (4 workers,
  no DB connection held) then one batched write. Previously the DB
  connection was held across every per-IMEI HTTP call, risking pool
  starvation.

Security
- _validate_token uses hmac.compare_digest for constant-time token
  comparison (closes timing side-channel).
- _parse_data_list caps incoming items at WEBHOOK_MAX_ITEMS (default
  5000) so a pathological push cannot blow memory.

Tests
- Fix test_null_alarm_type_skipped: its INSERT-count assertion was
  catching the ingestion_log insert written by log_ingestion. Filter
  that out so the test checks only data-table inserts.
- Full suite: 66 passed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 00:33:55 +03:00
David Kiania
f7cc48cc6a chore: align .python-version to 3.12.0 (matches Docker image and pyproject.toml) 2026-04-12 21:41:43 +03:00
David Kiania
20d3ddb841 feat: add db_audit health checks, runner, and scheduled Forgejo workflow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 21:40:29 +03:00
David Kiania
6ed4d3a1e2 test: add test suite - unit tests, webhook endpoint tests, and CI workflow
57 unit tests covering clean helpers, API signing, and field mapping fixes
(FIX-E06, FIX-M16, BUG-01, BUG-03); integration tests for webhook endpoints
with mocked DB; Forgejo CI workflow with TimescaleDB service container.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 21:38:20 +03:00
David Kiania
2ca3d2f021 ci: add ruff + mypy static analysis config and Forgejo workflow 2026-04-12 21:32:33 +03:00
David Kiania
75d3417a2b docs: add quality program design spec 2026-04-12 21:31:56 +03:00
David Kiania
f9834564ab Add CLAUDE.md and project docs for structured Claude project
CLAUDE.md: cached context file covering project identity, tech stack,
codebase map, schema quick-ref, API gotchas, fix history, working rules,
fleet state, and open items. Structured for maximum cache efficiency —
stable content first, dynamic state at the end.

docs/CONNECTIONS.md: connection parameter shapes (no secrets) for SSH,
DB, API, container resolution, Forgejo, Grafana, n8n.

docs/PROJECT_CONTEXT.md: client business context (telco field service,
3 cities, service types), data quality gaps, KPI framework by domain,
integration roadmap.

docs/KPI_FRAMEWORK.md: living KPI register with status tracking,
thresholds, client feedback log, and review checklist. To be co-developed
with client iteratively.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 20:59:15 +03:00
David Kiania
2131faf8c6 Add 260412 baseline report — first trip data, FIX-M16 confirmed
Post-deployment snapshot at ~00:15 EAT 2026-04-12. Key changes vs 260410:
- 3 trips recorded (FRED KMGW 538W HULETI, 6.94 km total) — pipeline validated
- FIX-M16 distance unit fix confirmed: implied speed matches API avgSpeed exactly
- 70 track_list fixes in 24h (was 13) — dense trail from active driving
- KDK 829A GP returned to primary depot from secondary Nairobi East cluster
- Uganda anomaly (X3-63282) persists — flagged for management
- Driver name root cause confirmed: not assigned in Tracksolid Pro UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 00:14:27 +03:00
David Kiania
6a0ceb78dd Fix trip distance unit (metres→km) and full device sync on upsert
[FIX-M16] jimi.device.track.mileage returns distance in metres despite
docs claiming km. Confirmed: avgSpeed × runTimeSecond / 3600 = distance/1000.
poll_trips() now divides raw value by 1000 before storing as distance_km.
3 existing bad rows corrected in prod DB (distance_km / 1000).

[FIX-M17] sync_devices() ON CONFLICT clause was only updating 5 of 26
fields, silently dropping driver_phone, sim, iccid, vehicle_name, status
etc. on subsequent syncs. Expanded to update all device fields so driver
assignments made in Tracksolid Pro UI propagate to DB on next daily sync.

Add sync_driver_audit.py: one-shot script to compare API vs DB device
registry, report driver/IMEI gaps, and force a full field upsert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 00:06:57 +03:00
David Kiania
fcc745f09d Fix Grafana provisioning: bake datasource/dashboard config into custom image
Coolify only copies docker-compose.yaml and .env to its working directory —
the ./grafana/provisioning bind mount source was always empty on the server,
so Grafana started with no datasource or dashboard configured (causing the
'Failed to load home dashboard' error).

Fix: build a custom Grafana image (grafana/Dockerfile) that COPYs the
provisioning directory at image build time. Grafana substitutes
${GRAFANA_DB_RO_PASSWORD} at startup from the env var now in Coolify's store.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 22:18:44 +03:00
David Kiania
d706d17cc8 Fix Grafana datasource: add GRAFANA_DB_RO_PASSWORD and sync grafana_ro on startup
grafana_ro DB role was created with placeholder password 'SET_PASSWORD_IN_ENV'
and GRAFANA_DB_RO_PASSWORD was never set in .env, so Grafana's TracksolidDB
datasource could not authenticate — causing 'Failed to load home dashboard'.

Fix:
- Add GRAFANA_DB_RO_PASSWORD to .env with a secure generated password
- Add sync_role_passwords() to run_migrations.py — runs ALTER ROLE on every
  startup so DB password stays in sync with the env var (idempotent)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 19:22:30 +03:00
David Kiania
87ecab4a72 Wire /pushevent to device_events table (was log-only)
LOGIN/LOGOUT events from Jimi now persist to tracksolid.device_events.
Table already existed with correct schema (imei, event_type, event_time,
timezone, unique constraint). Follows same SAVEPOINT + log_ingestion
pattern as all other DB-writing endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 18:42:22 +03:00
David Kiania
b1e4d6e85f Fix 5 webhook bugs: SAVEPOINTs, NULL guards, BCD timestamps, /pushevent, log NULL fix
BUG-01: OBD event_time — try unix_to_ts before clean_ts (Jimi sends epoch ints)
BUG-02: push_alarm — guard alarm_type not null (NULL breaks ON CONFLICT dedup)
BUG-03: push_trip_report — _parse_trip_ts handles Jimi BCD format YYMMDDHHmmss
BUG-04: SAVEPOINT per item in all 5 DB endpoints (FK violation on one item no
        longer aborts the whole batch; SAVEPOINT now inside try for safety)
BUG-05: Add /pushevent endpoint (log-only; was returning 404 to Jimi)
FIX:    push_fault_info — skip null fault_code (NULL != NULL in PG unique index)
FIX:    log_ingestion — pass SQL NULL not string "None" when no error occurred

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 18:19:13 +03:00
David Kiania
1f11a65b0b Add 02_tracksolid_docker_commands.md — remote DB command reference
Comprehensive reference for SSH + docker exec psql access to the
TimescaleDB instance on rahamafresh.com. Covers:

- How it works (SSH → docker exec → psql layers explained)
- tsdb() shell function setup for the server
- Mac one-liners for single queries, interactive sessions, piping SQL files
- Fleet & live positions queries (active vehicles, silent devices, anomalies)
- Trips & movement (today's KPIs, speeding, after-hours, utilisation rate)
- Alarms (summary, unacknowledged, acknowledge)
- Parking & idle time
- Position history & route replay
- Ingestion pipeline health checks
- Device registry (metadata gaps, odometer, subscriptions)
- Schema & migration operations
- Container & service operations (logs, restart, disk, chunk sizes)
- Quick reference table for all flags

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 08:23:01 +03:00
David Kiania
ae5bd2c960 Update tracksolidApiDocumentation.md with live implementation findings
Reflects accurate field names, behaviours, and status from production:

Polling endpoints:
- 5.1 location.list: add full response schema (direction, gpsSignal, gpsNum,
  powerValue, elecQuantity, posType, locDesc); add implementation note
  (311 calls, ~19 devices/sweep, ~200ms, missing devices silently omitted)
- 5.4 track.mileage: add maxSpeed field (BUG-03); add distance unit note
  (BUG-02 — values are km from API, corrected via migration 04)
- 5.5 track.list: add altitude/satellite fields; add POLL-01 implementation
  note (30-min schedule, 35-min lookback, source='track_list', ~137s/call)
- 5.7 parking: clarify acc_type=0 required; note durSecond vs stopSecond;
  add POLL-02 production status (60 calls, 0 rows, overnight expected)
- Rate limits: document track.list latency (~137s per call)

Alarms:
- 6.1: replace vague note with explicit poll-vs-push field name table
  (alertTypeId/alarmTypeName vs alarmType/alarmName); confirm BUG-01 fix
  verified in production (type 3 / "Vibration alert" now stored correctly)

Webhooks:
- 10.1 /pushevent: mark implemented (PUSH-01), db table
- 10.2 /pushhb: mark as not yet wired, table ready
- 10.4 /pushalarm: mark implemented, cross-ref field name table
- 10.7 /pushoil: mark implemented (PUSH-02), unit int→text note
- 10.9 /pushtem: mark implemented (PUSH-03)
- 10.10 /pushlbs: mark implemented (PUSH-04)
- 10.20 /pushobd: mark implemented, document OBD scalar extraction
- 10.21 /pushfaultinfo: mark not yet wired, table ready
- 10.22 /pushtripreport: mark implemented

Appendix B: full rewrite — split into polling and push tables with
accurate status (/⚠️/not used), call counts, and DB table references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 07:52:28 +03:00
David Kiania
d7ffa136a3 Regenerate 260410_baseline_report.md from live database (post-migration)
Full live-query refresh against tracksolid_db at 07:38 EAT 2026-04-11.
All data sourced directly from the server via 10 targeted psql queries.

Report covers: all 17 table row counts, full 63-device registry with
odometer/SIM/expiry, live position detail for all 19 reporting devices
with GPS signal quality, geographic cluster map, position_history by
source (poll=124 / track_list=13 = 137 total), alarm detail confirming
BUG-01 fix, ingestion log health (399 calls, 0 failures), subscription
status breakdown, silent device full list (44 devices), schema additions
verification, Grafana readiness matrix, and P0/P1/P2 action plan.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 07:42:33 +03:00
David Kiania
f277532a9d Regenerate 260410_baseline_report.md with post-migration comprehensive data
Updated report reflects state after migrations 04 and 05 are fully applied.
Includes: all 13 table row counts, fleet composition (63 devices / 4 models),
live position coverage (19/63), position history breakdown by source (poll vs
track_list), alarm detail (2 vibration alerts, BUG-01 fix confirmed), schema
health checklist, ingestion log polling summary, odometer service flags,
Uganda anomaly flag for X3-63282, data quality gap priority table, and
Grafana readiness assessment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 07:29:49 +03:00
David Kiania
5f1b32f1dc Extend seed sentinels to cover migrations 04 and 05
Containers share one DB — when ingest_movement applies 04, ingest_events
and webhook_receiver start later and find distance_m already renamed,
causing a spurious FATAL before the next restart catches the recorded row.

Added sentinels for all four migrations so any container self-heals
on first startup regardless of which container ran first:
  04 — trips.distance_km column exists
  05 — tracksolid.device_events table exists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:48:30 +03:00
David Kiania
5d47eece6b Fix: seed pre-tracking migrations to skip already-applied 02 and 03
Migration 02 and 03 were applied before the schema_migrations tracking
table existed, so they had no record and the runner tried to re-run them,
hitting non-idempotent TimescaleDB policy/trigger/cagg statements.

seed_pre_tracking_migrations() checks for sentinel schema objects and
inserts records for any migration that was clearly already applied:
  - 02: tracksolid.devices table exists
  - 03: position_history.altitude column exists

Called immediately after ensure_tracking_table() on every startup.
Safe on fresh databases (objects absent → nothing seeded → runs normally).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:43:44 +03:00
David Kiania
63e555b822 Fix: create tracksolid schema before schema_migrations table
On a fresh database the tracksolid schema doesn't exist yet —
migration 02 creates it, but ensure_tracking_table() ran first.
Added CREATE SCHEMA IF NOT EXISTS tracksolid before the table DDL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:40:32 +03:00
David Kiania
aa290151ea Update run_migrations.py: add 04+05, idempotency tracking, expanded verify
- Add 04_bug_fix_migration.sql and 05_enhancement_migration.sql to list
- Use schema_migrations table to skip already-applied migrations (prevents
  migration 04's RENAME from failing on re-run after first deployment)
- Expand CRITICAL_TABLES to include all 5 new tables from migration 05
- record_applied() writes to schema_migrations after each success
- Cleaner output: APPLY / SKIP / OK per file with summary count

On next Coolify redeploy each container will skip 02-05 (already applied)
and apply any new migrations added in future commits.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:34:57 +03:00
David Kiania
20a98074a6 Add idempotent migration runner script
run_migrations.sh auto-discovers numbered SQL files (NN_*.sql),
tracks applied migrations in tracksolid.schema_migrations table,
and skips already-applied files — safe to run on every deployment.

Usage: bash /app/run_migrations.sh
Coolify: add to Post-deployment Command in service settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:31:57 +03:00
David Kiania
97b19eb968 Add 2026-04-10 baseline fleet report from live database query
Captures first-night state of the tracksolid_db pipeline:
- 63 devices registered, 19 with live positions, 4 active today
- 3 vehicles with fresh GPS (<10 min): Westlands x2, Athi River x1
- X3-63282 located in Uganda — flagged for investigation
- KDK 829A GP (239k km) and Belta KCU-647D (234k km) flagged for service review
- Migration 04 and 05 not yet applied (distance_m column still present)
- Parking fix and trip polling not yet active (containers not redeployed)
- Prioritised action list for full operational readiness

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:20:16 +03:00
David Kiania
40e452e156 Replace hardcoded container names with dynamic lookup
Coolify regenerates the container suffix on every redeploy, making
hardcoded names stale. All three docs now use:
  TS_DB=$(docker ps --filter "name=timescale_db" --format "{{.Names}}" | head -1)

OPERATIONS_MANUAL.md: replaced bare connection string with full
  tsdb() shell function, one-liner pattern, and multi-container
  label-filter guidance.
tracksolid_DB_manual.md: updated header and connection example.
01_BusinessAnalytics.md: updated Step 5 migration commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 23:09:01 +03:00
David Kiania
09b3860706 Add fleet business analytics document
Covers fleet utilisation, driver behaviour (speeding, harsh driving,
tardiness, after-hours movement), real-time dispatch queries, km per
driver per day, full business question inventory, Grafana dashboard
blueprint, and the 5-step roadmap to unlock remaining capabilities.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 22:57:36 +03:00
David Kiania
3797a4e2ca Implement POLL-01 high-res GPS trails and POLL-03 on-demand location refresh
POLL-01 (FIX-M14): Add poll_track_list() calling jimi.device.track.list
- Runs every 30 min with 35-min lookback window (5-min overlap prevents gaps)
- Inserts all device waypoints into position_history with source='track_list'
- Increases position density from ~1/min to 2-6 fixes/min per active vehicle
- Single shared DB connection for all devices per cycle (efficient)

POLL-03 (FIX-M15): Add get_device_locations() utility function
- Calls jimi.device.location.get for up to 50 specific IMEIs on demand
- Used for alarm enrichment, stale device recovery, dashboard precision refresh

Manual updates:
- position_history section rewritten to document dual ingestion sources
- Three new queries: data density check, harsh driving detection, route trace
- Known Data Issues: issues 10 and 11 added and marked Fixed
- API coverage table updated to reflect all three endpoints now in use

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 22:46:00 +03:00
David Kiania
d534aceadc Add DB connection string to ops manual, add administration notes, remove stale deploy guide
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 22:34:56 +03:00
David Kiania
05993100e9 Enhance tracksolid_DB_manual.md with full analytics suite
- Add sections 16–21: Daily, Weekly, Monthly, Quarterly analytics,
  new table docs (device_events, fuel_readings, temperature_readings,
  lbs_readings, geofences), and updated Known Data Issues
- Fix all distance queries: remove erroneous /1000000.0 division
  (column is now distance_km in kilometres after migration 04)
- Update alarms section to reflect BUG-01 field mapping fix
- Update parking section to reflect POLL-02 acc_type/durSecond fix
- Rewrite "verify distance" section as accuracy cross-check query
- Expand row count query to include 5 new tables from migration 05

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 22:33:06 +03:00
David Kiania
c05b47abe2 Fix alarm field mapping, distance unit bug, parking params; add schema migrations
BUG-01 [FIX-E06]: jimi.device.alarm.list poll response uses alertTypeId/
alarmTypeName/alertTime, not the webhook field names. All 1,054 stored alarm
records had null alarm_type/alarm_name as a result. Corrected field mapping
in ingest_events_rev.py; also added alarm_name and source columns to INSERT.

BUG-02 [FIX-M11/M12]: trips.distance_m was storing millimetres due to an
erroneous * 1000 on an already-km API value. Removed the multiplication in
poll_trips() and push_trip_report(). Column renamed to distance_km in
migration 04 (historical rows divided by 1,000,000 to correct to km).
All SQL in both ingestion files updated to reference distance_km.

POLL-02 [FIX-M13]: parking poll returned 0 rows because the required
account and acc_type=0 parameters were missing. Also fixed response field
mapping: durSecond was incorrectly read as 'seconds'.

Migration 04: corrects and renames distance_m → distance_km.
Migration 05: adds normalized OBD columns, alarm/device enrichment columns,
new tables (device_events, fuel_readings, temperature_readings, lbs_readings,
geofences), expands dwh_gold fact table, and adds refresh_daily_metrics() ETL.

tracksolid_DB_manual.md updated to reflect column rename and mark fixed issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 22:18:30 +03:00
David Kiania
791bf2700c Add Ubuntu instance deployment guide
Step-by-step setup guide covering system updates, hostname/timezone,
sudo user creation, SSH hardening, UFW firewall, CrowdSec with nftables
bouncer, Zsh shell setup, and instance verification commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 16:40:05 +03:00
David Kiania
82761e1e3f Add Grafana NOC operational manual
Covers pre-deployment checklist, post-deploy verification steps for each
panel, database verification queries, troubleshooting guide, and
day-to-day NOC operations reference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:12:48 +03:00
David Kiania
cd6b2ca81a Add Grafana NOC fleet dashboard with provisioning
Adds a fully-provisioned Grafana dashboard for NOC operators to monitor
80 vehicles in real-time: live geomap with direction arrows, speed, driver
info, and color-coded plates. Includes datasource and dashboard provider
YAMLs, dashboard JSON (schemaVersion 39 / Grafana 11.0.0), and
docker-compose updates to mount provisioning at container start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:01:52 +03:00
David Kiania
2f3879aa2a Add n8n workflow templates and change webhook port to 8888
Port 8000 was already in use on the host. Updated uvicorn to listen
on 8888. Added 6 importable n8n workflow JSON files for Jimi push
data forwarding (OBD, faults, alarms, GPS, heartbeats, trips).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 18:54:42 +03:00
David Kiania
004fed7ab9 Add operations manual with verification queries per service
Comprehensive guide covering:
- Service architecture and scheduled tasks
- Per-service verification SQL queries grouped by service
- Health dashboard queries for monitoring
- Polling vs push coexistence and dedup strategy
- Environment variables, data retention, troubleshooting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:59:05 +03:00
David Kiania
e1402f6af1 Fix NoneType crash: API returns null result instead of missing key
dict.get("result", []) returns None when key exists with null value.
Changed to resp.get("result") or [] which handles both cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:27:48 +03:00
David Kiania
326764e1a0 Fix migration failures: switch to full TimescaleDB + use psql runner
- Change image from timescaledb-ha:pg16-ts2.15-oss to pg16-ts2.15
  (OSS edition lacks compression, retention, continuous aggregates)
- Add postgresql-client to Dockerfile for psql binary
- Rewrite run_migrations.py to use psql instead of psycopg2
  (psql runs each statement independently; psycopg2 wraps the
  entire file in one transaction so one error rolls back everything)
- Add schema verification: exits 1 if critical tables missing,
  preventing services from starting with broken schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:17:58 +03:00
David Kiania
3bbf3b777d Run migrations inline at each service startup instead of init service
Coolify doesn't support service_completed_successfully dependency.
Each Python service now runs 'python run_migrations.py' before its
main process. SQL is idempotent so concurrent runs are safe.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:11:12 +03:00
David Kiania
4a31de30b1 Add db_migrate init service to auto-run SQL schema on deploy
- New run_migrations.py: executes 02_*.sql and 03_*.sql in order
- New db_migrate service: runs once before all other services start
- All services now depend on db_migrate (service_completed_successfully)
- Tolerates re-deploy: catches errors from already-existing objects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 17:02:09 +03:00
David Kiania
b59616c7aa Remove webhook_receiver host port binding (Coolify proxy handles routing)
Port 8000 was already allocated on the host. On Coolify, Traefik routes
external traffic to the container internally — no host port needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:49:52 +03:00
David Kiania
2fbd286d29 Fix timescale_db: remove empty ports key causing Coolify deploy failure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:42:20 +03:00
David Kiania
77bc3a9eca Remove .DS_Store from tracking (now in .gitignore)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:31:17 +03:00
David Kiania
de70972d6a Add webhook receiver, consolidate shared utilities, expand telemetry coverage
- Add FastAPI webhook receiver (webhook_receiver_rev.py) for Jimi push data:
  OBD diagnostics, DTC fault codes, alarms, GPS, heartbeats, trip reports
- Add schema migration (03_webhook_schema_migration.sql) for webhook tables:
  fault_codes, heartbeats, expanded obd_readings/trips/position_history/alarms
- Consolidate duplicated _safe/_shutdown into shared safe_task/setup_shutdown
  in ts_shared_rev.py (DRY refactor)
- Add auto-commit to get_conn() context manager (prevents forgotten commits)
- Fix poll_trips to capture runTimeSecond and maxSpeed from API
- Add poll_parking via jimi.open.platform.report.parking
- Remove broken poll_obd (OBD is push-only, no polling endpoint exists)
- Fix alarms schema: add lat/lng/acc_status columns + dedup constraint
- Fix obd_readings schema: add dedup constraint
- Fix trigger DO block: replace nonexistent has_column with information_schema
- Narrow api_post exception handling to RequestException/ValueError
- Add webhook_receiver service to docker-compose.yaml
- Add fastapi/uvicorn/python-multipart to pyproject.toml
- Add clean_ts timestamp validator to ts_shared_rev.py
- Add Tracksolid Pro API documentation (tracksolidApiDocumentation.md)
- Populate .gitignore with Python/OS/secrets patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 16:31:17 +03:00
85b50db71a Update docker-compose.yaml 2026-04-07 21:53:11 +00:00
bdd26472e7 Update docker-compose.yaml
Changing port to 5599 to avoid confilict
2026-04-07 20:00:16 +00:00
David Kiania
6205c483ee Deploy v2.0 Production Telemetry Stack 2026-04-07 21:34:40 +03:00
David Kiania
0ce5d521db first commit 2026-04-07 20:41:16 +03:00