Skip to content

Sowel Specs Index

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

Foundations (V0.x) β€” core engine

# Title Status Summary
001 V0.1 MQTT devices βœ… First integration with Zigbee2MQTT bridge. Raw device auto-discovery via MQTT.
002 V0.1 UI scaffolding devices βœ… Initial React frontend with device list.
003 V0.2 Zones βœ… Hierarchical nestable zones. Parent-child tree structure.
004 V0.3 Equipments βœ… User-facing equipments that bind to devices via data keys.
005 V0.5 UI restructuring βœ… Navigation overhaul (home, zones, equipments, devices, admin).
006 V0.6 Sensor equipments βœ… Temperature, humidity, motion, luminance sensor types.
007 V0.7 Zone aggregation βœ… Auto-compute zone metrics from equipment data (motion=OR, temp=AVG, etc.).
008 Shutter equipments βœ… Position + state + cover orders (open/close/stop).
009 V0.8 Recipes βœ… Automation engine with typed slots. First built-in recipes.
010 V0.9 Modes βœ… Named zone-level states (Day/Night/Away) with impacts.
011 V0.10a Integration plugin architecture πŸ” superseded by 040, 053 Initial plugin interface for integrations.

V0.10 β€” built-in integrations (most are now πŸ” externalized as plugins)

# Title Status Summary
012 V0.10b Panasonic Comfort Cloud πŸ” β†’ 050 Panasonic AC cloud API polling (now a plugin).
013 V0.10c MCZ Maestro πŸ” β†’ 049 MCZ pellet stove Socket.IO integration (now a plugin).
014 V0.10d Netatmo Home+Control πŸ” β†’ 048a, 048b, 048c Netatmo HC integration (now split into 3 plugins: weather, control, energy).

V0.11 β€” logging, backup, shutters UX

# Title Status Summary
015 V0.11 Logging system βœ… Pino structured logging, ring buffer, module tagging, UI log viewer.
016 V0.8b Motion Light enhancements βœ… Motion-light recipe refinements (time slots, override, fallback).
017 V0.11b Backup hardening πŸ” β†’ 046, 058, 060 First backup system (export/import).
018 Recipes roadmap βœ… (meta) Roadmap document for planned recipes.
019 V0.8c Switch light βœ… Switch-light recipe (toggle on button press).
020 V0.8e Presence thermostat βœ… Presence-based thermostat setpoint logic with cocoon.
021 V0.8f Zone commands βœ… Zone-level order batching (allShuttersOpen/Close, allLightsOn/Off).

UX & dashboard

# Title Status Summary
022 Dark mode βœ… 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.
031 Notification publishers βœ… Telegram / webhook / FCM / ntfy notification channels.
032 State watch recipe βœ… Generic data-key watch with alarm recipe.
033 Dashboard widgets βœ… Customizable zone widgets on dashboard.
034 Progressive Web App βœ… PWA manifest, service worker (NetworkOnly for /api/), offline banner.
035 Energy dashboard βœ… Day/week/month/year energy breakdown with HP/HC classification.
036 Order dispatch error handling βœ… Graceful fallback when order publish fails.
037 Panasonic CC connection resilience πŸ” β†’ 050 Reconnect logic for Panasonic Comfort Cloud.
038 MCZ connection resilience πŸ” β†’ 049 Reconnect logic for MCZ Maestro.
039 Integrations page redesign βœ… Unified integrations page (list, configure, status).

Plugin system V2 (crucial β€” current architecture)

# Title Status Summary
040 Plugin engine 🟑 superseded by 053 First generation plugin engine (install from local zip).
041 Weather forecast plugin βœ… Open-Meteo-based weather forecast plugin (reference example).
042 Weather forecast equipment βœ… Equipment type for forecast data display.
043 Plugin update βœ… In-place plugin update from GitHub release.
044 Plugin SmartThings βœ… Samsung SmartThings plugin (polling + orders).
045 Plugin SmartThings OAuth βœ… OAuth2 flow for SmartThings authentication.
046 Backup v2 πŸ” β†’ 058, 060 Revised backup format (includes InfluxDB line protocol).
047 Prebuilt plugins βœ… Plugin distribution via GitHub releases (tarball).

V1.0 β€” externalizing all integrations as plugins

# Title Status Summary
048a Plugin Netatmo Weather βœ… Externalized Netatmo Weather Station integration.
048b Plugin Legrand Control βœ… Externalized Legrand Home+Control (lights/shutters/plugs).
048c Plugin Legrand Energy βœ… Externalized Legrand energy monitoring (NLPC meters).
049 Plugin MCZ Maestro βœ… Externalized MCZ Maestro integration.
050 Plugin Panasonic CC βœ… Externalized Panasonic Comfort Cloud integration.
051 Plugin LoRa2MQTT βœ… LoRa2MQTT bridge as plugin.
052 Plugin Zigbee2MQTT βœ… Zigbee2MQTT as plugin (last built-in to be externalized).
053 Package manager βœ… Major refactor: PackageManager service manages all packages (integrations + recipes). GitHub-based distribution with plugins/registry.json.
054 Recipe packages βœ… Recipes externalized as packages (same distribution model as plugins).
055 Versioning + CI/CD + Docker βœ… GitHub Actions release workflow, scripts/release.sh, ghcr.io image, semver tags. Introduced v1.0.0.

V1.0+ β€” self-update & deployment

# Title Status Summary
057 Self-update UI πŸ” β†’ 060 Initial self-update via UI (had race condition).
058 Backup completeness βœ… 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).
072 Order dispatch β€” netatmo-security Planned Migrate netatmo-security (single param: monitoring).
073 Order dispatch β€” smartthings Planned Migrate smartthings (command names stored in plugin memory).
074 Order dispatch β€” cleanup Planned Remove v1 retro-compat. Drop dispatch_config column from device_orders.

Pool equipments

# Title Status Summary
081 Pool equipments βœ… pool_pump, pool_cover types with candidate-based binding for multi-channel relays
082 Pool pump schedule βœ… Recipe plugin with 3 daily on/off slots
083 Pool heat pump (Polytropic) βœ… pool_heat_pump type + Modbus integration plugin (Polytropic Master Inverter)

Shelly energy refactor (multi-iteration)

# Title Status Summary
084 Shelly energy β€” overview Planned Guiding principles for the 4-iteration migration from Legrand to Shelly Pro 3EM
085 Iteration 1 β€” shelly-em plugin (live) Planned Sowel plugin: live act_power + counters per channel, side-by-side with Legrand
086 Iteration 2 β€” Shelly drives roles Planned Promote Shelly channels to main_energy_meter + energy_production_meter, retire Legrand
087 Iteration 3 β€” energydata-stack Rejected Replaced by hardware-native archive on Shelly Pro 3EM (60d in-device); see 088 for the actual fix
088 Iteration 4 β€” Shelly gap backfill Planned Plugin queries EM1Data.GetData RPC on boot + hourly to replay missing minutes through the live pipeline

V1.5 β€” by-usage chart, MQTT toggles, state-trigger recipe

# Title Status Summary
090 MQTT mapping enable/disable βœ… 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.

V1.7 β€” WAN hardening & security

# Title Status Summary
105 WAN hardening βœ… 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.

V1.11 β€” plugin runtime hardening

# Title Status Summary
111 Plugin soft isolation βœ… 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.

How to use this index after context loss

  1. Find the theme you need via section headers above
  2. Open specs/XXX-name/spec.md for requirements and acceptance criteria
  3. Open specs/XXX-name/architecture.md for technical design, data model changes, file-level impact
  4. Open specs/XXX-name/plan.md for implementation steps

For the current plugin-based architecture, start with spec 053 (PackageManager) β€” it's the root of everything plugin-related.

For self-update, start with spec 060 β€” it supersedes spec 057 and is the current design.

For the full system overview, see technical/architecture.md.

For production operations (deploy, backup, self-update, logs), see technical/deployment.md.