update to 0.13.3 #57
@@ -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/),
|
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).
|
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
|
## [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.
|
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.
|
||||||
|
|||||||
@@ -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.
|
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
|
## Features
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ Base.metadata.create_all(bind=engine)
|
|||||||
ENVIRONMENT = os.getenv("ENVIRONMENT", "production")
|
ENVIRONMENT = os.getenv("ENVIRONMENT", "production")
|
||||||
|
|
||||||
# Initialize FastAPI app
|
# Initialize FastAPI app
|
||||||
VERSION = "0.13.2"
|
VERSION = "0.13.3"
|
||||||
if ENVIRONMENT == "development":
|
if ENVIRONMENT == "development":
|
||||||
_build = os.getenv("BUILD_NUMBER", "0")
|
_build = os.getenv("BUILD_NUMBER", "0")
|
||||||
if _build and _build != "0":
|
if _build and _build != "0":
|
||||||
|
|||||||
@@ -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`.
|
||||||
Reference in New Issue
Block a user