diff --git a/CHANGELOG.md b/CHANGELOG.md index b20bad3..edba477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,40 @@ All notable changes to Terra-View will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.13.3] - 2026-06-05 + +Calibration sync from SFM events. Closes the manual data-entry loop on calibration dates — Terra-View now pulls `device.calibration_date` from each seismograph's most recent event sidecar once a day and updates `RosterUnit.last_calibrated` when the device reports something fresher than what's stored. Manual edits still win when they're newer than the latest event; a fresh event arriving later supersedes the manual edit. Adds a "Sync now" button under Settings → Advanced → Calibration Defaults for on-demand runs, and a `docs/ROADMAP.md` to track in-flight + deferred work. + +### Added + +- **Calibration sync service** (`backend/services/calibration_sync.py`). Per-unit: fetches `/db/events?serial={id}&limit=1` then `/db/events/{event_id}/sidecar` via the SFM proxy, reads `device.calibration_date`, and writes it to `RosterUnit.last_calibrated` with `next_calibration_due` recomputed from `UserPreferences.calibration_interval_days`. Every change is logged in `UnitHistory` with `source='sfm_event'` and `notes="Synced from event {id}"` so the unit detail history timeline reflects auto-sync activity alongside manual edits. +- **Conflict rule: events-as-truth, manual wins when newer.** Three outcomes per unit: + - `already_in_sync` — stored date already matches the event's calibration date. + - `skipped_manual_newer` — the latest `UnitHistory` change for `last_calibrated` happened *after* the event's timestamp, so the manual edit is preserved. Only a future event can supersede it. + - `updated` — the event is newer (or no manual edit exists), so the stored date is replaced. +- **Daily background job at 03:15 local** via the `schedule` library + a worker thread (modeled on `backup_scheduler.py`). Started in `main.py`'s startup hook, stopped on shutdown. Does not run on boot — first sync after a server start fires at the next 03:15. +- **`POST /api/calibration/sync`** — runs a full sync immediately and returns a summary `{checked, updated, skipped_manual_newer, already_in_sync, no_event, no_sidecar, no_cal_in_sidecar, errors, results: [...]}`. Powers the Settings button. +- **`GET /api/calibration/sync/status`** — returns scheduler state + the last run's summary including per-unit `{unit_id, action, old, new, event_id}` rows. Useful for diagnostics: `curl localhost:8001/api/calibration/sync/status | jq`. +- **Settings UI: "Sync from SFM events" section** under the Calibration Defaults card (Advanced tab). Click "Sync now" → result line shows counts: `Checked N · Updated N · Already in sync N · Manual kept N · No event N`. +- **`docs/ROADMAP.md`** — first-pass roadmap pulling deferred items from `CLAUDE.md`'s focus block, in-code TODOs (`photos.py` GPS migration → `MonitoringLocation`, `device_controller.py` SFM Phase 2 stubs, `modem_dashboard.py` ModemManager backend, `dashboard.html` geocoding), and the README's long-standing "Future Enhancements" wishlist. Grouped into In Flight / Near-Term / Medium-Term / Wishlist; intended as a living document. + +### Fixed + +- **Prod startup crash: `ModuleNotFoundError: No module named 'schedule'`**. The `schedule` library wasn't pinned in `requirements.txt` even though `backend/services/backup_scheduler.py` has been using it since v0.4.x — the dev image happened to have it from an earlier manual `pip install`, but a clean prod rebuild dropped it. Added `schedule==1.2.2` so the new calibration scheduler (and the existing backup scheduler) survive a clean rebuild. + +### Upgrade Notes + +No DB migration required — `UnitHistory.source` and `RosterUnit.last_calibrated`/`next_calibration_due` already exist. Rebuild only: + +```bash +cd /home/serversdown/terra-view +docker compose build terra-view && docker compose up -d terra-view +``` + +After rebuild, Settings → Advanced → "Sync from SFM events" → "Sync now" to backfill in one shot; otherwise wait for the 03:15 job. + +--- + ## [0.13.2] - 2026-05-30 PWA-cache fix for mobile operators. v0.13.0 added the inline PDF preview, `.TXT` download, and Review form to `event-modal.js`, but mobile devices using Terra-View as a PWA never saw any of it — the service worker had `CACHE_VERSION = 'v1'` (unchanged since v0.12.x), so the activate handler never evicted the stale cache and mobile users kept getting served the pre-v0.13.0 modal forever. diff --git a/README.md b/README.md index 32f2afd..df2cbd5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Terra-View v0.13.2 +# Terra-View v0.13.3 Backend API and HTMX-powered web interface for managing a mixed fleet of seismographs and field modems. Track deployments, monitor health in real time, merge roster intent with incoming telemetry, and control your fleet through a unified database and dashboard. ## Features diff --git a/backend/main.py b/backend/main.py index 8e8219d..54792ad 100644 --- a/backend/main.py +++ b/backend/main.py @@ -30,7 +30,7 @@ Base.metadata.create_all(bind=engine) ENVIRONMENT = os.getenv("ENVIRONMENT", "production") # Initialize FastAPI app -VERSION = "0.13.2" +VERSION = "0.13.3" if ENVIRONMENT == "development": _build = os.getenv("BUILD_NUMBER", "0") if _build and _build != "0": diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..b3adc16 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,67 @@ +# Terra-View Roadmap + +Living document — captures known deferred work, in-flight initiatives, and longer-term ideas. +Bump items up/down or strike them through as priorities shift. Source of truth for "what's next" +should be this file plus the `## Current Development Focus` block in `CLAUDE.md`. + +Last updated: 2026-06-05 (Terra-View v0.13.3) + +--- + +## In Flight + +Work that's started or has obvious next steps in the code. + +- **SFM Integration Phase 2 — device control** — expose `/device/*` (start, stop, erase, push-config) + through the Terra-View proxy. Blocked on SFM growing an auth layer; placeholder TODOs already in + `backend/services/device_controller.py` (lines 73, 109, 207, 282, 582). +- **Calibration sync from SFM events** — done in v0.13.x. Daily 03:15 job + Settings "Sync now" button. + Future: surface "last sync" timestamp on unit detail; per-unit "sync this one" action. +- **Synology NAS deployment** — doc lives at `docs/SYNOLOGY_DEPLOYMENT.md`. Need to actually deploy + + write up what tripped us up vs. the doc's expectations. + +## Near-Term + +Concrete things scoped but not started. + +- **Migrate GPS coord parse in `photos.py`** — currently writes to dead `RosterUnit.coordinates` + field. Should write to the active `MonitoringLocation` instead (matches the location-as-truth + refactor done elsewhere). Helper: `backend/services/unit_location.py`. +- **Phase 3 — drag-to-resize deployment bars** on the fleet-wide deployment-history Gantt + (`/tools/deployment-history`). Phase 2 (the calendar + Gantt tabs) shipped in v0.12.0. +- **Phase 5c — swap-detection daily job** — placeholder card already in `templates/tools.html:162`. + Auto-detects unit swaps in the field (BE12345 → BE67890 at the same project+location) from + operator-typed metadata. Pairs with a notification inbox. +- **Geocoding for address strings** — TODO in `templates/dashboard.html:913`. Lets locations without + explicit coordinates still appear on maps. +- **ModemManager backend** — `backend/routers/modem_dashboard.py:279` has a TODO for querying a real + modem backend. Currently the modem dashboard is mostly read-only metadata. + +## Medium-Term + +Bigger features, sketched but not designed in detail. + +- **Alerting** — email/SMS for missing units, calibration-expiring-soon, sync failures. + README's "Future Enhancements" has had this for a while; would pair well with the existing + `UserPreferences` thresholds. +- **Multi-user auth** — currently single-tenant, no login. Probably the prerequisite for any + cloud-hosted multi-customer deployment. +- **Notification inbox** — central place for swap-detection alerts, sync errors, calibration + warnings, FT-flag review queue, etc. +- **Audit log UI** — `UnitHistory` already records everything; expose a filterable view. + +## Long-Term / Wishlist + +Speculative. Promote up the list once there's a concrete need. + +- PostgreSQL backend for larger deployments (SQLite is fine for now) +- Advanced filtering / saved searches on roster + events +- Export roster in additional formats (XLSX, GeoJSON) +- Public-facing project status pages (read-only, share-link gated) +- SLM module parity with seismographs — modal-based event/measurement detail similar to SFM modal +- Weather station / accelerometer / GPS tracker modules (new device-type modules following the + SLMM pattern — see `CLAUDE.md` → "Adding a New Device Type Module") + +## Done / Reference + +For shipped items, see `CHANGELOG.md`. For architecture decisions, see `CLAUDE.md`.