This file is a navigation aid over specs/. Every spec under specs/XXX-name/ typically contains three files: spec.md (requirements + acceptance criteria), architecture.md (technical design), plan.md (implementation steps).
Use this index to quickly recover context: scan descriptions, find the relevant spec, then read the full folder for details.
Specs are grouped by theme and annotated with status:
β active β implemented and in production
π superseded β replaced by a later spec (follow the arrow)
π‘ partial β implemented, but scope has evolved
Tailwind class-based dark mode with user preference.
023
Sunrise / sunset
β
SunCalc-based sunlight manager with offset settings.
024
Motion light split
β
Split motion-light into basic + dimmable variants.
025
V0.13 History (InfluxDB)
β
Time-series history for numeric device data.
026
V0.8 Cocoon thermostat
β
Bedtime cocoon logic for presence thermostat.
027
V0.8 Presence heater
β
Presence-based heater recipe (eco/comfort).
028
MQTT publishers
β
Outbound MQTT publisher manager (mappings from events to topics). v1.2.6: onChangeOnly option β publish only on value change to avoid flooding external displays with periodic heartbeats.
029
MQTT brokers
β
Multi-broker support for MQTT publishers.
030
Logging audit
β
Consolidated log level strategy and module taxonomy.
Auto-download missing plugins on startup; dynamic data file scan; FK-safe restore.
059
Remote registry + backup fix
β
Remote plugins/registry.json fetch with cache + local fallback. InfluxDB ensureBuckets before restore.
060
Self-update helper + detection improvements
β
Current self-update architecture: helper container pattern (spawn docker:25-cli that survives sowel death), auto pre-update backup in data/backups/ (rotate keep 3), 1h version poll, WebSocket push of update.available, "Check for updates" button, composeManaged detection.
061
Timezone from home location
β
Auto-derive process.env.TZ from home.latitude/home.longitude via tz-lookup at boot (runs before createLogger() to avoid V8 TZ caching). Endpoints GET /system/timezone + POST /system/restart (helper container). UI: TZ in Settings, CurrentTimePill in header, RestartToast on location change.
062
Water valve equipment
β
New water_valve equipment type with custom valve icon, water widget family, zone aggregation (open/total + flow sum), zone pill, dashboard widget (close-all), and detail card with toggle + timed watering. Targets SONOFF SWV and similar smart irrigation valves. Foundation for future auto-watering recipe (spec 063).
Order dispatch refactoring (progressive migration)¶
#
Title
Status
Summary
067
Order dispatch β core + lora2mqtt
β
New executeOrder(device, orderKey, value) signature with v1 retro-compat. First migration: lora2mqtt v2.0.0. Enum case-insensitive resolution.
068
Order dispatch β zigbee2mqtt
β
Migrate z2m plugin to v2.0.0 (apiVersion 2). Composite payload support preserved.
069
Order dispatch β legrand-control
Planned
Migrate legrand-control (cloud API IDs stored in plugin memory).
070
Order dispatch β panasonic-cc
Planned
Migrate panasonic-cc (guid/param stored in plugin memory).
071
Order dispatch β mcz-maestro
Planned
Migrate mcz-maestro (commandId stored in plugin memory).
Per-mapping enabled flag on MQTT publishers, complementing the existing publisher-level toggle. UI power-off icon + reduced opacity for disabled rows. Lets users silence a single mapping (seasonal source) without losing its configuration.
091
By-usage consumption chart
β
New GET /energy/by-usage endpoint and a Total / By usage toggle on the Energy page rendering a stacked breakdown per submeter energy_meter + an "Other" residual (main meter - Ξ£ submeters).
092
State-triggered light recipe
β
New external recipe plugin state-trigger-light (in plugins/registry.json). Turns lights on for a fixed duration when a watched equipment's state alias transitions to a target value. Optional nightOnly filter via the sunlight manager. Introduces crossZone and includeDescendants slot constraints.
Closes WAN-exposure gaps: @fastify/helmet (CSP/HSTS/X-Frame-Options), CORS default tightened from * to localhost, WebSocket mandatory auth via Sec-WebSocket-Protocol subprotocol + Origin validation, non-root container via entrypoint+gosu (transparent upgrade from root-owned volumes), docker.sock self-update opt-in via override file, auth-by-default invariant on all /api/v1/* routes.
Scoped Proxies wrap each plugin's PluginDeps (settings, event bus, device manager). Enforces 4 invariants at the JS layer: settings scoped to integration.<own-id>.*, event whitelist of system.* types, device ownership forced by integrationId, and error confinement on lifecycle methods. Unconditional since v1.11.0. No breaking change for plugin authors.
112
Process crash handlers
β
Global uncaughtException and unhandledRejection listeners installed at boot. A throw that escapes every other guard now produces a structured fatal log line (stdout + data/logs/sowel.N.log) before the process exits, so Docker's restart policy reboots the container with a usable trace instead of a silent loop. Audit F03, spec 112. Shipped in v1.11.1.
113
Audit log
β
Persistent SQLite trail of every security-sensitive action (auth, user CRUD, settings, mode, backup, plugin). New audit_log table + AuditLogger service called from API route handlers with actor and IP context. Admin-only GET /api/v1/audit endpoint with pagination and filtering. 365-day retention purged at boot. Sensitive values redacted from meta. Audit F13, spec 113. Shipped in v1.11.1.
New awning equipment type (sibling of shutter) with its own awnings widget family and dedicated V3 colored illustration (window + cassette + 10 trapezoidal scalloped stripes when deployed, retracted fringe when closed). Reuses shutter_position / shutter_move / set_shutter_position categories β any integration emitting them can drive an awning. Three zone commands allAwningsExtend/Stop/Retract. Companion plugin sowel-plugin-somfy-rts for the somfyrts2mqtt ESP32+CC1101 bridge. Shipped in v1.13.0.
Weather station widget rework: dedicated outdoor module section (temperature, humidity, min/max envelope), bindings exposed on the device selector. Outdoor module integration across 4 layers (DeviceSelector, bindingUtils, SENSOR_DATA_CATEGORIES, CATEGORY_DEFAULTS_ON) so the Netatmo outdoor module historizes by default and shows in Analyse. Same-category label disambiguation in humanBindingLabel (suffix with device name when several bindings of the same category coexist on the chart). Shipped in v1.14.x.
V1.15 β Analyse calendar navigator + live submeter breakdown¶
#
Title
Status
Summary
116
Equipment availability
π Draft
Propagate equipment availability (offline / degraded / online) from device state to equipment level, with UI badges and aggregated zone status. Drafted 2026-05-24, ~1.5-2 days. Not started.
Min/max envelope on line charts at 1h / 1d resolution (semi-transparent band around the mean, with a global "Enveloppe min/max" toggle). Bar chart for rain/energy-only selections in AnalyseView (mirrors isCumulativeBarChart already used by HistoryPanel). Proper daily rain total computed locally by the Netatmo backfill (sum_rain_24 daily bucket = sum of 48 raw 30-min values). Backfill safety: only delete aliases the run can restore, plus --only=<filter> to scope re-runs. Documents the 2026-05-30 sowelox rain data-loss incident and the recovery path.