Releases: srcfl/ftw
Release list
v1.1.0
🛰️ Mostly Harmless
Don't Panic.
Minor Changes
- 644d784: Add feature-negotiated commercial reserve, backup, robust forecast, degradation, and demand-charge constraints to optimizer protocol v1 for shared Sourceful Local EMS use.
v1.0.0
🛰️ Hyperspace Bypass
Don't Panic.
Major Changes
- 2801fca: Remove the retired Forty Two Watts relay, TURN/WebRTC owner portal, local
passkey sessions,ftw-pairsupport tunnel, anonymous relay fleet reporter,
and their API, UI, configuration, deployment and release surfaces. The FTW
dashboard is now explicitly LAN-local; owner-operated VPN access remains a
community path, while the planned managed remote experience is the optional
Sourceful Energy app through outbound-only Novacore integration.
v0.130.4
🛰️ Marvin
Don't Panic.
Patch Changes
-
ed59d81: Answer health probes during slow boots.
The API port is now bound before the state DB opens, serving
/api/healthwith 200{"status":"starting"}(and 503 elsewhere) until
the real mux takes over on the same listener. Previously a boot that ran
a one-time VACUUM or a full integrity check on a multi-GB database left
the port unbound for up to tens of minutes, so the Docker healthcheck
failed and the self-update sidecar judged the deploy failed and rolled
back in the middle of the compaction.
v0.130.3
🛰️ Marvin
Don't Panic.
Patch Changes
-
00a9da5: Yield between maintenance chunks so live writers are never starved.
v0.130.2 bounded every maintenance transaction, but back-to-back chunks
still starved the control loop during a large backlog migration: SQLite's
busy handler retries without fairness, so the maintenance loop re-acquired
the write lock before any waiting writer won its retry. Prune chunks,
rolloff deletes, and diagnostics batch-deletes now pause (250/100 ms)
between transactions, guaranteeing every waiting writer a window.
v0.130.2
🛰️ Marvin
Don't Panic.
Patch Changes
-
1b62749: Critical fix: bounded maintenance transactions (upgrade-lock incident).
The first history prune after upgrading a long-running install (v0.129.0's
Prune wiring) could hold SQLite's write lock for hours: the hot→warm
aggregation used a correlated subquery that re-scanned the hot table once
per 15-minute bucket, and the whole backlog ran as one transaction. Every
control-loop write failed with SQLITE_BUSY until it finished.- Prune is now linear (single-pass bucket aggregation) and chunked: each
transaction ages at most ~24 h of rows, so writers interleave. A 93-day
backlog that previously locked the DB for 4+ hours now completes in
seconds. Chunk and cutoff boundaries are bucket-aligned, which also fixes
a pre-existing partial-bucket overwrite at the retention edge. - Prune logs its result (rows aged, chunks, duration) — maintenance is no
longer silent. - Parquet rolloff deletes each day's rows right after that day's file is
durable, in hour-sized transactions, instead of one giant end-of-run
DELETE that could lose the race against live writers. - Planner-diagnostics retention in SQLite reduced 30 → 7 days (measured
485 MB at 30 days on a real site; Parquet keeps everything), deletes are
batched, and the table is excluded from state snapshots (snapshots shrink
from ~470 MB to ~20 MB).
- Prune is now linear (single-pass bucket aggregation) and chunked: each
v0.130.1
🛰️ Marvin
Don't Panic.
Patch Changes
- d08c4cc: Automatically add and validate the independently updatable optimizer sidecar when upgrading safe existing Linux or macOS Compose installations, with rollback cleanup and fail-closed handling for operator-owned overrides.
v0.130.0
🛰️ Marvin
Don't Panic.
Minor Changes
- eba5722: Add independently updatable optimizer and Lua-driver modules with protocol negotiation, signed monorepo driver releases, content-addressed activation, selective restart, health verification, and rollback while retaining bundled and Go-DP safety fallbacks. Add explicit opt-in anonymous fleet statistics for active installations and public driver/component health.
Patch Changes
- a4f0b33: Repair the setup wizard and pair-session component after the FTW rename, and add CI guards for browser JavaScript, release metadata, and stale Changeset package names.
v0.129.0
🛰️ Improbability Drive
Don't Panic.
Minor Changes
-
8d61001: Add Sungrow PV curtail support, reset stale inverter control state when the driver loads, and surface hardware fault states such as thermal shutdowns in diagnostics.
-
af005b9: Database hardening and richer history access.
Durability & SD-card resilience
- Parquet rolloff now fsyncs day files (and their directory) before the atomic rename — a power cut can no longer lose a day of rolled-off samples whose SQLite rows were already deleted.
- The rolloff streams one UTC day at a time instead of buffering the whole backlog in memory (a multi-week backlog could OOM a Pi and then never complete).
- Planner-diagnostics day files are merged instead of overwritten — the hourly rolloff previously discarded every earlier hour of the same day from cold storage.
- One-time
VACUUMat boot when a large share of state.db is freelist (reclaims the high-water mark left by big prunes), guarded by a free-disk check. - Truncating WAL checkpoint after every hourly rolloff; each control-loop tick (history + metrics) is now persisted in a single transaction, halving the WAL commit rate.
Faster history queries
- Downsampled
/api/historyand/api/seriesqueries aggregate per bucket in SQL instead of fetching every raw row into Go (a month view used to materialize >1M rows per request), and buckets carry a min/max envelope so short power spikes stay visible zoomed out.
Richer history over REST
/api/serieswindows older than 14 days transparently include the cold Parquet tier./api/seriessupports comma-separated multi-metric queries, absolutesince/untilbounds, andformat=csvexport./api/series/catalogreports each metric's display unit; units fromhost.emit_metricare now persisted across restarts.
Growth control
- New
state.cold_retention_daysconfig bounds the cold Parquet tier (default 0 = keep everything). - Low-disk warning (log + event feed) when free space drops below 500 MB.
Patch Changes
-
af005b9: Run the wide-history retention tiers during the hourly storage rolloff so old full-resolution dashboard rows are aggregated instead of growing
state.dbindefinitely. -
a4c695a: Decouple the Raspberry Pi installer image from application releases and reduce redundant CI work while retaining required validation.
-
3e1b98a: Fail closed for direct state-changing
p2pFetchAPI calls on public relay origins so owner ceremony and control request bodies are never raw-fetched to the relay.Enable short TCP keepalive on Modbus TCP driver sockets to make stale inverter sessions recover faster after network/controller interruptions.
Use MyUplink's known-working OAuth scope set by default and expose an override for installations that can use narrower read-only auth.
Let
BatteryCoversEVtake effect in passive-arbitrage PV-surplus charge slots by allowing the planned-grid cap to back off charging and cover EV import while preserving deliberate grid-charge slots.Resolve failed remote-home P2P attempts to the actionable sign-in/setup gate instead of leaving the page on "Reaching your home..." forever.
v0.128.1
🛰️ Mostly Harmless
Don't Panic.
Patch Changes
- dcffc61: Add a one-command, rollback-safe migration from legacy Docker Compose and
local-development images to the official Sourceful images. Include license
and notice files in Docker build contexts so canonical main and updater images
publish successfully. - 43e2d1b: Repair self-updates from legacy or developer Compose layouts by applying a
temporary canonical image override without rewriting the host deployment, and
preserve automatic image and state rollback on that path. Add a bilingual
legacy-upgrade runbook and refresh migration/operator documentation,
fresh-clone simulator defaults, driver catalog coverage, release-image
selection, and license payloads after the Sourceful transfer.
FTW drivers (stable)
Moving stable channel for independently released FTW Lua drivers. Trust manifest.json only after Ed25519 verification.