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.