Aller au contenu

Index des specs Sowel

Ce fichier sert d'aide à la navigation sur specs/. Chaque spec sous specs/XXX-name/ contient typiquement trois fichiers : spec.md (exigences + critères d'acceptation), architecture.md (design technique), plan.md (étapes d'implémentation).

Utilisez cet index pour récupérer rapidement le contexte : parcourez les descriptions, trouvez la spec pertinente, puis lisez le dossier complet pour les détails.

Les specs sont regroupées par thème et annotées d'un statut :

  • active : implémentée et en production
  • 🔁 superseded : remplacée par une spec ultérieure (suivez la flèche)
  • 🟡 partial : implémentée, mais le périmètre a évolué

Fondations (V0.x) : moteur central

# Title Status Résumé
001 V0.1 MQTT devices Première intégration avec le bridge Zigbee2MQTT. Auto-découverte de devices brute via MQTT.
002 V0.1 UI scaffolding devices Frontend React initial avec liste de devices.
003 V0.2 Zones Zones imbriquables hiérarchiquement. Structure parent-enfant en arbre.
004 V0.3 Equipments Équipements user-facing qui se lient aux devices via des clés de données.
005 V0.5 UI restructuring Refonte de la navigation (home, zones, équipements, devices, admin).
006 V0.6 Sensor equipments Types de capteurs température, humidité, mouvement, luminance.
007 V0.7 Zone aggregation Calcul auto des métriques de zone depuis les données d'équipement (motion=OR, temp=AVG, etc.).
008 Shutter equipments Position + état + ordres de cover (ouvrir/fermer/stop).
009 V0.8 Recipes Moteur d'automatisation avec slots typés. Premières recettes intégrées.
010 V0.9 Modes États nommés au niveau zone (Day/Night/Away) avec impacts.
011 V0.10a Integration plugin architecture 🔁 superseded by 040, 053 Interface plugin initiale pour les intégrations.

V0.10 : intégrations natives (la plupart sont maintenant 🔁 externalisées en plugins)

# Title Status Résumé
012 V0.10b Panasonic Comfort Cloud 🔁 → 050 Polling de l'API cloud des climatiseurs Panasonic (maintenant un plugin).
013 V0.10c MCZ Maestro 🔁 → 049 Intégration Socket.IO du poêle à granulés MCZ (maintenant un plugin).
014 V0.10d Netatmo Home+Control 🔁 → 048a, 048b, 048c Intégration Netatmo HC (séparée maintenant en 3 plugins : weather, control, energy).

V0.11 : logging, backup, UX volets

# Title Status Résumé
015 V0.11 Logging system Logging structuré pino, ring buffer, tagging par module, viewer de logs UI.
016 V0.8b Motion Light enhancements Affinements de la recette motion-light (créneaux horaires, override, fallback).
017 V0.11b Backup hardening 🔁 → 046, 058, 060 Premier système de backup (export/import).
018 Recipes roadmap ✅ (meta) Document roadmap pour les recettes prévues.
019 V0.8c Switch light Recette switch-light (bascule à l'appui sur bouton).
020 V0.8e Presence thermostat Logique de consigne thermostat basée sur la présence avec cocoon.
021 V0.8f Zone commands Batching d'ordres au niveau zone (allShuttersOpen/Close, allLightsOn/Off).

UX et tableau de bord

# Title Status Résumé
022 Dark mode Dark mode basé sur la classe Tailwind avec préférence utilisateur.
023 Sunrise / sunset Sunlight manager basé sur SunCalc avec réglages d'offset.
024 Motion light split Séparation de motion-light en variantes basique et dimmable.
025 V0.13 History (InfluxDB) Historique en série temporelle pour les données numériques de devices.
026 V0.8 Cocoon thermostat Logique cocoon au coucher pour le thermostat de présence.
027 V0.8 Presence heater Recette de radiateur basée sur la présence (éco/confort).
028 MQTT publishers Manager de publisher MQTT sortant (mappings d'événements vers topics). v1.2.6 : option onChangeOnly, publication seulement au changement de valeur pour ne pas inonder les afficheurs externes.
029 MQTT brokers Support multi-broker pour les publishers MQTT.
030 Logging audit Stratégie consolidée des niveaux de log et taxonomie des modules.
031 Notification publishers Canaux de notification Telegram / webhook / FCM / ntfy.
032 State watch recipe Surveillance générique de clé de donnée avec recette d'alarme.
033 Dashboard widgets Widgets de zone personnalisables sur le tableau de bord.
034 Progressive Web App Manifest PWA, service worker (NetworkOnly pour /api/), bandeau offline.
035 Energy dashboard Ventilation jour/semaine/mois/année avec classification HP/HC.
036 Order dispatch error handling Fallback gracieux quand la publication d'un ordre échoue.
037 Panasonic CC connection resilience 🔁 → 050 Logique de reconnexion pour Panasonic Comfort Cloud.
038 MCZ connection resilience 🔁 → 049 Logique de reconnexion pour MCZ Maestro.
039 Integrations page redesign Page intégrations unifiée (liste, configuration, statut).

Système de plugins V2 (crucial, architecture actuelle)

# Title Status Résumé
040 Plugin engine 🟡 superseded by 053 Première génération de moteur de plugins (install depuis zip local).
041 Weather forecast plugin Plugin de prévisions météo basé sur Open-Meteo (exemple de référence).
042 Weather forecast equipment Type d'équipement pour l'affichage des données de prévision.
043 Plugin update Mise à jour de plugin in-place depuis une release GitHub.
044 Plugin SmartThings Plugin Samsung SmartThings (polling + ordres).
045 Plugin SmartThings OAuth Flux OAuth2 pour l'authentification SmartThings.
046 Backup v2 🔁 → 058, 060 Format de backup révisé (inclut le line protocol InfluxDB).
047 Prebuilt plugins Distribution de plugins via les releases GitHub (tarball).

V1.0 : externalisation de toutes les intégrations en plugins

# Title Status Résumé
048a Plugin Netatmo Weather Intégration Netatmo Weather Station externalisée.
048b Plugin Legrand Control Legrand Home+Control externalisé (lumières/volets/prises).
048c Plugin Legrand Energy Suivi énergétique Legrand externalisé (compteurs NLPC).
049 Plugin MCZ Maestro Intégration MCZ Maestro externalisée.
050 Plugin Panasonic CC Intégration Panasonic Comfort Cloud externalisée.
051 Plugin LoRa2MQTT Bridge LoRa2MQTT en tant que plugin.
052 Plugin Zigbee2MQTT Zigbee2MQTT en tant que plugin (la dernière intégration native à être externalisée).
053 Package manager Refactor majeur : le service PackageManager gère tous les paquets (intégrations + recettes). Distribution basée sur GitHub avec plugins/registry.json.
054 Recipe packages Recettes externalisées en tant que paquets (même modèle de distribution que les plugins).
055 Versioning + CI/CD + Docker Workflow de release GitHub Actions, scripts/release.sh, image ghcr.io, tags semver. Introduit en v1.0.0.

V1.0+ : auto-update et déploiement

# Title Status Résumé
049 Externalize MCZ Maestro as Plugin Livrée. Voir specs/049-plugin-mcz-maestro/.
050 Externalize Panasonic CC as Plugin Livrée. Voir specs/050-plugin-panasonic-cc/.
051 Externalize LoRa2MQTT as Plugin Livrée. Voir specs/051-plugin-lora2mqtt/.
052 Externalize Zigbee2MQTT as Plugin Livrée. Voir specs/052-plugin-zigbee2mqtt/.
053 PackageManager Extraction + Plugin Adaptation Livrée. Voir specs/053-package-manager/.
054 Recipe Packages Livrée. Voir specs/054-recipe-packages/.
055 Versioning 1.0.0, CI/CD & Docker Livrée en v1.0.0. Voir specs/055-versioning-cicd-docker/.
057 Self-update UI 🔁 → 060 Premier auto-update via l'UI (avait une race condition).
058 Backup completeness Auto-téléchargement des plugins manquants au démarrage ; scan dynamique des fichiers de données ; restauration FK-safe.
059 Remote registry + backup fix Récupération de plugins/registry.json à distance avec cache + fallback local. InfluxDB ensureBuckets avant restauration.
060 Self-update helper + detection improvements Architecture actuelle d'auto-update : pattern de container helper (spawn docker:25-cli qui survit à la mort de sowel), backup pré-update auto dans data/backups/ (rotation, conserve 3), poll de version 1 h, push WebSocket de update.available, bouton "Check for updates", détection composeManaged.
061 Timezone from home location Auto-dérivation de process.env.TZ depuis home.latitude/home.longitude via tz-lookup au boot (s'exécute avant createLogger() pour éviter le caching TZ V8). Endpoints GET /system/timezone + POST /system/restart (container helper). UI : TZ dans Réglages, CurrentTimePill dans le header, RestartToast au changement de localisation.
062 Water valve equipment Nouveau type d'équipement water_valve avec icône custom de vanne, famille de widget water, agrégation de zone (open/total + somme de débit), pastille de zone, widget tableau de bord (close-all), et carte de détail avec toggle + arrosage minuté. Cible les SONOFF SWV et vannes connectées similaires. Base pour une future recette d'auto-arrosage (spec 063).

Refactoring du dispatch d'ordre (migration progressive)

# Title Status Résumé
063 Auto-watering recipe plugin Livrée en v1.1.0. Voir specs/063-auto-watering-recipe/.
064 Weather computed rain data + cumulative bar charts Livrée en v1.1.0. Voir specs/064-weather-computed-rain/.
065 Freecooling recipe plugin Livrée en v1.1.2. Voir specs/065-freecooling-recipe/.
066 Registry independence from Sowel releases Livrée en v1.2.0. Voir specs/066-registry-independence/.
067 Order dispatch — core + lora2mqtt Nouvelle signature executeOrder(device, orderKey, value) avec rétro-compat v1. Première migration : lora2mqtt v2.0.0. Résolution d'enum insensible à la casse.
068 Order dispatch — zigbee2mqtt Migration du plugin z2m vers v2.0.0 (apiVersion 2). Support des payloads composites préservé.
069 Order dispatch — legrand-control Planned Migration de legrand-control (IDs API cloud stockés en mémoire du plugin).
070 Order dispatch — panasonic-cc Planned Migration de panasonic-cc (guid/param stockés en mémoire du plugin).
071 Order dispatch — mcz-maestro Planned Migration de mcz-maestro (commandId stocké en mémoire du plugin).
072 Order dispatch — netatmo-security Planned Migration de netatmo-security (paramètre unique : monitoring).
073 Order dispatch — smartthings Planned Migration de smartthings (noms de commande stockés en mémoire du plugin).
074 Order dispatch — cleanup Planned Suppression de la rétro-compat v1. Suppression de la colonne dispatch_config de device_orders.

Équipements piscine

# Title Status Résumé
075 Order Dispatch: Legrand Energy Migration Livrée. Voir specs/075-order-dispatch-legrand-energy/.
076 Order Dispatch: Netatmo Weather Migration Livrée en v1.2.12. Voir specs/076-order-dispatch-netatmo-weather/.
077 Order Categories Livrée en v1.2.12. Voir specs/077-order-category/.
078 Button Zone Orders & Zone-First Equipment Selection Livrée en v1.2.14. Voir specs/078-button-zone-orders/.
079 Device Data Enum Values Livrée en v1.2.14. Voir specs/079-data-enum-values/.
080 Tasmota Plugin Integration Livrée en v1.2.15. Voir specs/080-tasmota-plugin/.
081 Pool equipments Types pool_pump, pool_cover avec liaison basée sur des candidats pour les relais multi-canaux
082 Pool pump schedule Plugin de recette avec 3 créneaux on/off journaliers
083 Pool heat pump (Polytropic) Type pool_heat_pump + plugin d'intégration Modbus (Polytropic Master Inverter)

Refactor énergétique Shelly (multi-itérations)

# Title Status Résumé
084 Shelly energy — overview Planned Principes directeurs pour la migration en 4 itérations de Legrand vers Shelly Pro 3EM
085 Iteration 1 — shelly-em plugin (live) Planned Plugin Sowel : act_power live et compteurs par canal, en parallèle de Legrand
086 Iteration 2 — Shelly drives roles Planned Promotion des canaux Shelly en main_energy_meter + energy_production_meter, retrait de Legrand
087 Iteration 3 — energydata-stack Rejected Remplacé par l'archive native du Shelly Pro 3EM (60 j in-device) ; voir 088 pour le correctif réel
088 Iteration 4 — Shelly gap backfill Planned Le plugin interroge la RPC EM1Data.GetData au boot et toutes les heures pour rejouer les minutes manquantes dans le pipeline live

V1.5 : graphique par usage, bascules MQTT, recette state-trigger

# Title Status Résumé
089 Security hardening: plugin supply chain & backup path safety Livrée en v1.6.2. Voir specs/089-security-hardening-supply-chain-backup/.
090 MQTT mapping enable/disable Flag enabled par mapping sur les publishers MQTT, en complément de la bascule au niveau publisher. Icône power-off UI + opacité réduite sur les lignes désactivées. Permet à l'utilisateur de mettre en sourdine un seul mapping (source saisonnière) sans perdre sa configuration.
091 By-usage consumption chart Nouvel endpoint GET /energy/by-usage et bascule Total / Par usage sur la page Énergie qui rend une ventilation empilée par sous-compteur energy_meter + un résidu "Other" (compteur principal - Σ sous-compteurs).
092 State-triggered light recipe Nouveau plugin de recette externe state-trigger-light (dans plugins/registry.json). Allume les lumières pour une durée fixe quand l'alias state d'un équipement surveillé transite vers une valeur cible. Filtre nightOnly optionnel via le sunlight manager. Introduit les contraintes de slot crossZone et includeDescendants.

V1.11 : durcissement runtime des plugins

# Titre Statut Résumé
094 UI Redesign (umbrella + Phase 0 palette swap) Livrée. Voir specs/094-ui-redesign/.
095 Design System Phase 1: Typography Polish Livrée. Voir specs/095-design-system-typography/.
096 Design System Phase 2: Sidebar Livrée. Voir specs/096-design-system-sidebar/.
097 Design System Phase 3: Strip Pills (Zone Aggregation) Livrée. Voir specs/097-design-system-strip-pills/.
098 Design System Phase 4: Dashboard Widgets Livrée. Voir specs/098-design-system-dashboard/.
099 Design System Phase 5: Equipment Row Livrée. Voir specs/099-design-system-equipment-row/.
100 Design System Phase 6: Zone View 2-Column Layout Livrée. Voir specs/100-design-system-comportements/.
101 Activity Feed (Zone view right column) Livrée en v1.8.0. Voir specs/101-design-system-activity-feed/.
102 Design System Phase 8: Recipe Edit Modal + Surcharges par mode Livrée. Voir specs/102-design-system-recipe-modal/.
104 Self-update resilience Livrée en v1.6.3. Voir specs/104-self-update-resilience/.
105 WAN Hardening Livrée en v1.7.0. Voir specs/105-wan-hardening/.
106 Make the topbar "update available" pill actionable Livrée en v1.9.0. Voir specs/106-update-pill-actionable/.
107 Surface a changelog link per row in the UpdatesSheet Livrée en v1.10.0. Voir specs/107-update-row-changelog-link/.
108 Block releases without release notes Livrée en v1.10.0. Voir specs/108-release-notes-required/.
109 Preserve bound device data/orders across partial re-discoveries Livrée en v1.10.1. Voir specs/109-device-discovery-preserve-bound/.
110 Category-first binding resolution across the codebase Livrée en v1.10.3. Voir specs/110-category-first-binding-resolution/.
111 Isolation soft des plugins Proxies scopés autour des PluginDeps de chaque plugin (settings, event bus, device manager). Quatre invariants enforces au niveau JavaScript : settings scopés à integration.<own-id>.*, whitelist d'events system.*, ownership des devices forcée par integrationId, et confinement des erreurs sur les méthodes lifecycle. Actif sans condition depuis v1.11.0. Pas de breaking change pour les auteurs de plugins.
112 Handlers de crash process Listeners globaux uncaughtException et unhandledRejection installés au boot. Un throw qui échappe à toutes les autres protections produit désormais une ligne fatal structurée (stdout + data/logs/sowel.N.log) avant que le process exit, pour que Docker relance le conteneur avec une trace exploitable au lieu d'une boucle silencieuse. Audit F03, spec 112. Livré en v1.11.1.
113 Journal d'audit Trail SQLite persistant de toute action sensible (auth, user CRUD, settings, mode, backup, plugin). Nouvelle table audit_log + service AuditLogger appelé depuis les route handlers avec contexte acteur et IP. Endpoint admin-only GET /api/v1/audit avec pagination et filtrage. Rétention 365 jours purgée au boot. Les valeurs sensibles sont redactées du meta. Audit F13, spec 113. Livré en v1.11.1.

V1.13 : store banne + bridge Somfy RTS

# Titre Statut Résumé
115 Store banne + bridge Somfy RTS Nouveau type d'équipement awning (frère du shutter) avec sa famille de widget awnings et une illustration V3 colorée dédiée (fenêtre + cassette + 10 bandes trapézoïdales festonnées en mode déployé, frise rétractée en mode fermé). Réutilise les catégories shutter_position / shutter_move / set_shutter_position — toute intégration qui les émet peut piloter un store banne. Trois commandes de zone allAwningsExtend/Stop/Retract. Plugin compagnon sowel-plugin-somfy-rts pour le bridge ESP32+CC1101 somfyrts2mqtt. Livré en v1.13.0.

V1.14 : UX station météo

# Titre Statut Résumé
114 UX station météo Refonte du widget station météo : section dédiée au module extérieur (température, humidité, enveloppe min/max), liaisons exposées sur le sélecteur d'appareils, historisation par défaut du module extérieur Netatmo, désambiguïsation des libellés de même catégorie sur les graphiques. Livré en v1.14.x.

V1.15 : navigateur calendrier Analyse + répartition sous-compteurs en direct

# Titre Statut Résumé
116 Disponibilité des équipements 📝 Brouillon Propager la disponibilité (hors ligne / dégradé / en ligne) de l'état des appareils vers les équipements, avec badges UI et statut agrégé par zone. Rédigée le 2026-05-24, non démarrée.
117 Calendrier Analyse + sous-compteurs Navigateur calendrier sur la vue Analyse (jour/sem/mois/année + flèches) remplaçant l'ancien sélecteur de plage, avec fenêtre absolue et axe X temporel. Donut de répartition des sous-compteurs en direct sur la page Énergie. Burger mobile pour Analyse. Livré en v1.15.0.
118 Améliorations graphiques Analyse 📝 Brouillon Enveloppe min/max sur les courbes en résolution 1h/1d, barres pour les sélections pluie/énergie, total de pluie journalier correct dans le backfill Netatmo, garde-fous du backfill (--only). Documente l'incident de perte de données pluie du 2026-05-30.

V1.17 - V1.19 : API historique énergie + afficheurs supervisés

# Titre Statut Résumé
119 Agrégation par période de l'historique énergie Les endpoints d'historique énergie renvoient des buckets pré-agrégés alignés calendrier (24 horaires pour le jour, 7 quotidiens pour la semaine, 28-31 pour le mois, 12 mensuels pour l'année) : plus de ré-agrégation côté client. Un seul aggregateWindow InfluxDB aligné sur le fuseau serveur, split HP/HC conservé par bucket. Livré en v1.17.0.
120 Type d'équipement afficheur Nouveau type display pour les écrans supervisés par Sowel (premier matériel : le firmware AMOLED sowel-energy-display) : page de détail firmware/uptime/rssi, langue et luminosité en ligne, famille de widgets displays avec agrégation en ligne/total par zone. Livré en v1.18.0.
121 Plugin MQTT de supervision d'afficheurs Plugin MQTT compagnon (repo séparé, désormais sowel-plugin-displays) découvrant les afficheurs via un payload state retained avec disponibilité LWT, exposés comme appareils liables à l'équipement de la spec 120. Contrat state + cmd/<key> réutilisable par tout futur afficheur. Livré avec v1.18.0.
122 Action de réveil des afficheurs Ordre display_wake sans valeur demandant à l'écran de restaurer la luminosité préférée de l'utilisateur depuis la NVS ; les recettes de veille par présence n'ont plus à connaître le niveau. Livré en v1.19.0.

V1.20 : valorisation en euros + mode ombre

# Titre Statut Résumé
123 Valorisation du coût énergie Bascule Wh/€ sur la page Énergie revalorisant historique, totaux et répartition par usage en euros via le tarif HP/HC existant. Coûts calculés à la lecture, aucun changement de schéma InfluxDB ; bascule persistée en localStorage. Livré en v1.20.0.
124 Mode ombre SOWEL_SHADOW_MODE=1 rend un conteneur sûr face à une copie de la production : l'UI fonctionne, tout ce qui sort (plugins, recettes, publishers MQTT/notifications, polling GitHub) est neutralisé au boot et au runtime. Log d'avertissement, endpoint système, bandeau ambre. Livré en v1.20.0.

V1.21 - V1.23 : solaire + briques recettes

# Titre Statut Résumé
125 Équipement panneau solaire + APsystems Nouvel équipement solar_panel en lecture seule (un équipement = un panneau = une voie d'onduleur) : puissance/énergie/tension/courant/température DC, widget dédié, groupe Solaire du dashboard. Catégorie temperature_device hors moyennes de pièce, plugin compagnon sowel-plugin-apsystems. Livré en v1.21.0.
126 Slot select + getSunlight() Les formulaires de recettes gagnent un slot select (liste fermée localisée) et les recettes ctx.helpers.getSunlight() (lever/coucher/jour avec offsets spec 023) : les briques derrière la recette Programmation horaire du store. Livré en v1.23.0.

V1.24 - V1.26 : notifications

# Titre Statut Résumé
127 Notifications Web Push (PWA) Push natif sur la PWA installée en HTTPS, à côté de Telegram : activation par appareil dans les réglages, puis mapping d'un publisher Web Push sur n'importe quelle valeur. Clés VAPID générées au premier boot, abonnements par utilisateur. Livré en v1.24.0 (correctifs iOS jusqu'en v1.24.3).
128 Répétition de notification Option explicite de re-notification : tant qu'une valeur mappée reste active (ex. alarme State Watch), la notification se renvoie à cadence fixe et s'arrête silencieusement quand ça se résout. Aucune / Indéfiniment / Limitée à N. Livré en v1.26.0.

V1.27 - V1.30 : mesure, arrosage, RBAC, triphasé

# Titre Statut Résumé
129 Interrupteur avec mesure Une prise/interrupteur affiche puissance et énergie en direct quand l'appareil les remonte (ex. SONOFF S60ZBTPF) : puissance à côté du bouton ON/OFF, alimentation du dashboard énergie et de la répartition en direct. Les relais simples ne changent pas. Livré en v1.27.0.
130 Jours de semaine par créneau d'arrosage Chaque créneau d'arrosage peut être limité à des jours choisis (vide = tous les jours), ex. 07:30 les jours d'école et 09:00 le week-end. Nouveau champ multi-select de recette rendu en puces. Livré en v1.28.0.
131 RBAC : configuration admin only Le rôle Standard est limité à voir et actionner : dashboards, états et commandes oui, mais aucune création/renommage/suppression ni configuration. Appliqué côté serveur (403) et masqué dans l'UI. Livré en v1.29.0. Amendé par l'issue #912 : activer, désactiver et appliquer un mode passent dans la liste blanche standard — le mode actif est un état d'exécution et une actuation, tandis que ce qu'un mode est reste réservé à l'admin.
132 Répartition par phase sur Énergie Live Les installations triphasées peuvent afficher une barre par phase sous le diagramme de flux : un compteur principal portant les liaisons power_l1/l2/l3 rend le déséquilibre visible d'un coup d'œil. Convention de liaison ouverte à toute intégration. Livré en v1.30.0.

V1.31 - V1.34 : caméra, min/max météo, chauffe-eau

# Titre Statut Résumé
133 Type d'équipement caméra Équipement camera indépendant du fabricant : instantané rafraîchi périodiquement (page de détail + widget), vue en direct HLS à la demande, contrôles surveillance/projecteur/sirène optionnels. Tous les médias passent par le backend : le navigateur ne parle jamais à la caméra ni au relais du fabricant. Livré en v1.31.0.
134 Min/max journalier météo Les stations météo affichent le min et le max mesurés du jour sous chaque température (widgets PC et mobile, page de détail, modules extérieur et intérieur). Sowel suit l'enveloppe lui-même à partir des échantillons déjà reçus : indépendant du fabricant, sans configuration, remise à zéro à minuit local. Livré en v1.32.0.
135 Équipement chauffe-eau Nouvel équipement water_heater : ON/OFF via le canal relais standard (Tuya WHD02 fonctionne directement), température de l'eau optionnelle sous son propre alias hors moyennes de pièce, puissance/énergie automatiques sur relais avec mesure, icône d'état de chauffe. Livré en v1.34.0.

V1.35 : sources personnelles de plugins

# Titre Statut Résumé
136 Sources personnelles de plugins Troisième niveau de confiance à côté d'officiel/communautaire (spec 089) : un admin enregistre ses propres dépôts GitHub publics comme sources de plugins, sans PR sur le registre central. Modèle TOFU : SHA256 du tarball affiché dans un modal de confirmation, épinglé en base, re-confirmation à chaque changement de contenu ; les restaurations de backup vérifient contre le hash épinglé. Nouvelle table plugin_sources, PersonalSourceManager, routes /api/v1/plugins/sources, badge Perso + section sources dans l'UI Plugins. Mergé le 2026-08-08 (#367), non livré.
137 Plugins Page: Recipe Categories and Search Livrée en v1.36.0. Voir specs/137-plugins-categories-search/.
138 Read-only tariff helper for recipes Livrée en v1.37.0. Voir specs/138-recipe-tariff-helper/.
139 Zone-qualified equipment pickers in recipe forms Livrée en v1.37.1. Voir specs/139-zone-qualified-recipe-pickers/.
140 Energy Capacity Arbiter Livrée en v1.39.0. Voir specs/140-energy-capacity-arbiter/.
141 Spec 141: Order Delivery Confirmation Livrée en v1.39.0. Voir specs/141-order-delivery-confirmation/.
142 Zone paths in the equipments admin list Livrée. Voir specs/142-equipments-list-zone-path/.
143 Spec 143: Low Battery Alerts Livrée en v1.43.0. Voir specs/143-low-battery-alerts/.
144 States and measurements on one Analyse chart Livrée en v1.42.0. Voir specs/144-analyse-mixed-state-axis/.
145 Series colours and Y axes on the Analyse chart Livrée en v1.43.0. Voir specs/145-analyse-series-color-and-y-axis/.
146 Confirmation before a sensitive gate action Livrée. Voir specs/146-gate-action-confirmation/.
147 Persist the activity feed and the arbiter decision journal Livrée. Voir specs/147-persist-activity-arbiter-history/.
148 Energy arbiter UI polish (design-system + redesigned timeline) Livrée. Voir specs/148-arbiter-ui-polish/.
149 Dashboard presentation resolver (phase 1) Livrée. Voir specs/149-dashboard-presentation-resolver/.
150 Typed value normalization at ingestion + unified binding candidates Livrée en v1.48.0. Voir specs/150-value-normalization-unified-binding/.
151 Two-Factor Authentication (TOTP + Backup Codes) Livrée. Voir specs/151-mfa-totp/.
152 Equipment solar command channel Livrée en v1.52.0. Voir specs/152-equipment-solar-command/.
153 VMC (2-speed ventilation) equipment type Livrée. Voir specs/153-vmc-equipment/.
154 Per-equipment invert direction for shutter-family equipments Livrée en v1.52.5. Voir specs/154-shutter-invert/.
155 Invert Direction for Boolean Gate Triggers (issue #627) Livrée. Voir specs/155-gate-invert-direction/.
156 UPS (uninterruptible power supply) equipment type Livrée en v1.53.0. Voir specs/156-ups-equipment/.
157 Shared FlowDiagram, and the UPS panel rebuilt on it Livrée en v1.54.0. Voir specs/157-flow-diagram/.
158 Arbiter baseline metrics Livrée en v1.55.0. Voir specs/158-arbiter-metrics/.
159 Weather forecast: multi-model and ensemble confidence Livrée en v1.56.0. Voir specs/159-weather-forecast-multi-model/.
160 PV production forecast Livrée en v1.57.0. Voir specs/160-pv-production-forecast/.
161 Fit the PV model from existing history Livrée en v1.57.0. Voir specs/161-pv-history-backfill/.
162 Tell the household when the panels stop performing Livrée en v1.58.0. Voir specs/162-pv-health/.
163 PV monitoring and configuration find their place Livrée en v1.58.0. Voir specs/163-pv-ui-reorg/.
164 Granted-but-idle on the arbiter timeline Livrée en v1.59.0. Voir specs/164-arbiter-timeline-idle-grant/.
165 One load-state model for the arbitration surface Livrée en v1.59.0. Voir specs/165-arbiter-state-model/.
166 Claimant-declared need for a granted load Livrée en v1.60.0. Voir specs/166-arbiter-claimant-need/.
167 Documentation currency gates Livrée. Voir specs/167-documentation-currency/.
168 Widget prévisions : bande 5 jours et panneau détail Livrée. Voir specs/168-forecast-widget-five-days/.
169 Tuile Dashboard pour une instance de recette Livrée. Voir specs/169-dashboard-recipe-widget/.
170 Une zone somme la puissance que ses sous-compteurs mesurent Livrée. Voir specs/170-zone-power-aggregate/.
171 Un clic sur une tuile de recette déclenche sa commande Livrée. La spec 169 a donné une tuile à une instance de recette et a laissé toute la carte inerte : une carte qui affichait « Prêt, un clic ouvre le Portail pour 15 min » ne faisait rien quand on cliquait, alors que tous les autres widgets actionnent au clic sur la carte depuis la spec 098. Une tuile qui n'affiche qu'une seule commande la déclenche désormais depuis toute la carte, même cycle et même valeur suivante que la pastille, qui reste là pour qui préfère viser ; deux commandes, aucune, une instance désactivée et le mode édition laissent la carte inerte. Comme cela transforme un carré de 240 px en ouvre-portail, le paquet déclare où la question de la confirmation est répondue : tile.confirmFrom nomme l'emplacement d'équipement que la commande actionne et le requireConfirmation de cet équipement (spec 146) décide alors seul, donc la réponse est donnée une fois et toutes les surfaces qui actionnent le portail posent la même question ; confirmParam la confie à l'instance là où aucun équipement ne peut être dérivé, et tile.confirm est le défaut du paquet. Sur mobile, une carte gardée ouvre la feuille glisser-pour-confirmer de la spec 146 ; la pastille n'est jamais gardée et le bureau ne confirme jamais. Voir specs/171-recipe-tile-primary-action/.
172 Le panneau des mises à jour sait terminer une mise à jour personnelle Livrée. Voir specs/172-updates-sheet-personal-confirm/.
173 Un compteur qui se trouve à l'intérieur d'un autre Livrée. Voir specs/173-nested-submeters/.
174 Une action minutée sur un équipement actionnable Phases 1 et 2 (moteur, API, et les deux surfaces d'usage). Rien dans le moteur ne savait dire « agis maintenant, reviens en arrière dans N minutes » : chaque occurrence était une recette tenant son propre minuteur — motion-light, state-trigger-light, delivery-gate — trois copies avec trois jeux de règles d'annulation qui divergeaient déjà. Un équipement porte désormais au plus un retour que le moteur lui doit, persisté en base plutôt qu'en setTimeout : une échéance encore devant survit à un redémarrage sur son reliquat, une échéance passée pendant l'arrêt part au retour — c'est le cas pour lequel la fonctionnalité existe. Quatre règles sont tranchées plutôt que découvertes : un retour fait à la main sur la mesure miroir désarme (agir plus tard déferait le geste de l'utilisateur, et sur une commande qui bascule rouvrirait le portail qu'il vient de fermer) ; un second armement de la même action repousse l'échéance sans rien envoyer (« ouvre encore », devant un portail ouvert, veut dire « laisse-moi plus de temps ») ; un retour qui n'a pas pu partir lève une alerte et s'arrête au lieu de rejouer à l'aveugle ; supprimer l'équipement emporte son échéance. Les deux moitiés passent par executeOrder, donc l'inversion (spec 154), la résolution de valeur (spec 150) et la confirmation de livraison (spec 141) sont héritées et non redites. La phase 2 configure la commande sur la page équipement et la rend sur la tuile Dashboard et la carte compacte, via UN seul composant de décompte partagé ; les trois surfaces restantes attendent la spec 149 (#325), qui hérite désormais d'une implémentation et non de cinq. Elle a aussi supprimé le refus d'une action et d'un retour de même valeur, qui excluait le portail à impulsion séquentielle pour lequel la fonctionnalité existe, et l'a remplacé par une règle d'éligibilité : l'équipement doit porter l'ordre et une mesure d'état qui lui est liée, sans quoi un retour fait à la main ne pourrait jamais terminer le créneau. Hors périmètre également : un replaySafe déclaré par l'intégration, qui transformerait la règle d'échec d'un défaut prudent en la bonne réponse. Voir specs/174-equipment-timed-action/.
175 Une mesure de puissance est jugée sur sa propre cadence Quatre surfaces décidaient si une puissance pouvait être affichée en direct, et elles se contredisaient : un compteur à trois minutes d'un cycle de 300 s parfaitement sain était silencieux dans la bannière Live, « périmé » sur sa tuile du Dashboard et retiré du total de sa zone, au même instant. Chacune tenait une constante déduite du TYPE d'équipement, qui ne dit rien de la fréquence à laquelle un appareil parle : main_energy_meter couvre aussi bien un Shelly à 1 Hz qu'un connecteur cloud à 300 s, et un seul chiffre est forcément faux pour l'un des deux. Le moteur dérive désormais la fenêtre de ce que fait réellement la source, l'intervalle médian entre ses arrivées récentes ou, à défaut, l'intervalle d'interrogation déclaré par son intégration, sous la forme clamp(2,5 x cadence, 120 s, 30 min), et la porte sur la liaison sous le nom freshnessBudgetMs. Les surfaces ne comparent plus qu'un âge à un nombre qu'on leur donne : la divergence disparaît par construction et non par discipline, et la détection suit la source, un compteur à 1 Hz qui meurt se voit en deux minutes au lieu de dix, un poller à 300 s garde son calme. L'estimateur vit en mémoire et sa statistique est une médiane, ce qui absorbe une coupure de six heures au milieu d'échantillons d'une seconde ; au redémarrage, on retombe sur la cadence déclarée puis sur dix minutes prudentes, plutôt que d'afficher tous les compteurs périmés au boot. Elle a aussi supprimé demand_5min, un alias que LIVE_POWER_ALIASES et la règle de budget traitaient à part au motif qu'un Legrand NLPC n'aurait pas de canal power : il en a un, aucun plugin du registre n'a jamais produit cet alias, et sa seule déclaration dans l'histoire du dépôt était une fixture de test. Hors périmètre, volontairement : le statut d'équipement de la spec 116 garde ses fenêtres par catégorie. Voir specs/175-cadence-derived-freshness/.
176 L'état de marche d'un thermostat a son propre alias Sur un thermostat sous-compté, l'alias power est la puissance de la pince (convention métering), et l'alias est unique par équipement : le booléen marche/arrêt rapporté par le device n'avait donc nulle part où vivre, et chaque surface UI comparait ce wattage à true, lisant l'unité comme éteinte en permanence. Le toggle ne se stabilisait jamais, chaque appui renvoyait ON (cinq ordres ON en 90 s mesurés en production avec la PAC à 2974 W), et l'extinction exigeait un double appui dans la fenêtre optimiste, car la carte effaçait TOUT l'état optimiste au moindre changement de donnée alors que la pince en pousse un toutes les quelques secondes. Même cause racine que l'issue #901, une couche au-dessus. Le booléen du device se lie désormais sous state, le MÊME alias marche/arrêt que tous les équipements à relais (aucun nouveau nom dans le data model ; portée limitée aux thermostats), et l'override de catégorie spec 152 le marque appliance_state : l'arbitre d'énergie le reconnaît comme état de marche tandis que le métering, l'intégrateur de sous-comptage et le panneau énergie ne le confondent jamais avec le wattage. Toute lecture marche/arrêt passe par un helper unique (l'alias state d'abord, un power booléen déclaré en repli, jamais un wattage), l'effacement optimiste devient par alias avec un TTL de 90 s en garde-fou, et deux bugs latents sont morts au passage : RELEVANT_DATA.thermostat datait d'avant les catégories spec 077 (un thermostat fraîchement lié perdait silencieusement power/consigne/sonde extérieure), et un ordre toggle_power s'aliasait state, que rien ne lit. Compagnon : panasonic-cc 2.3.2 ajoute un second poll à la demande à 45 s pour la latence de Comfort Cloud. Voir specs/176-thermostat-run-state/.
177 Ce qu'est un thermostat ; les extras rendus comme des extras Avant, un thermostat Sowel était ce que les devices Panasonic et MCZ exposaient : leurs clés (nanoe, airSwingUD, profile, resetAlarm) formaient la liste d'auto-liaison dans l'UI produit, un device devait porter la clé brute targetTemperature pour être proposé comme thermostat, et la carte avait une branche par fabricant — la cause derrière la spec 176, dont les propres mots étaient « un alias n'est pas un vocabulaire ». Le cœur est désormais déclaré une fois dans src/shared/thermostat-contract.ts (temperature, setpoint, state, power, operationMode, outsideTemperature optionnel), un device est un thermostat dès qu'il porte une catégorie setpoint / set_setpoint, la température de la pièce et le mode se résolvent par catégorie comme le reste du cœur (operation_mode / set_operation_mode rejoignent la taxonomie, valeurs auto/heat/cool/dry/fan/off), et un thermostat lie tous les ordres de son device — le cœur canonisé, le reste en extras sous sa propre clé. La carte mène avec le cœur et rend les extras génériquement d'après le type de l'ordre ; les branches resetAlarm, stoveState, profile, fanSpeed et ecoMode ont disparu. Aucun changement de donnée, de plugin, de liaison ni de migration : un thermostat existant garde toutes ses liaisons et tous ses contrôles. Partie 1 de l'issue #919 ; la partie 2 (#922) fait publier le contrat par les plugins. Voir specs/177-thermostat-contract/.
178 Appuyer encore demande plus longtemps, puis abandonne La spec 174 n'avait donné qu'un geste au moteur : un second appui prolonge le créneau de la même durée, indéfiniment. Cela répond « pas encore » mais jamais « combien de temps encore » — sur l'installation de référence, obtenir une heure sur un portail réglé à un quart d'heure demande quatre appuis identiques, et le contrôle ne peut pas dire ce que fera le suivant puisque tous font la même chose. Un équipement déclare désormais des PALIERS de durées (durationStepsMs, de deux à six, croissants) et un appui les gravit : le premier agit et arme le plus court, chaque suivant repousse l'échéance à maintenant + palier suivant sans rien envoyer, et un appui au-delà du dernier abandonne l'échéance sans revenir en arrière — le portail reste ouvert et plus rien ne le refermera. Ce dernier appui n'est volontairement pas le bouton d'annulation, qui envoie le retour : « arrêter le décompte » et « fermer maintenant » sont deux intentions, et chacune garde son contrôle. Le palier est persisté (timed_actions.step_index), pour qu'un redémarrage ne relance pas la montée en silence et ne transforme pas un appui d'abandon en une heure de plus. Des paliers modifiés sous un créneau en cours le replacent par sa durée et non par son indice, un indice stocké voulant dire autre chose dès que les paliers bougent. durationMs est aligné sur le premier palier à l'écriture : deux endroits prétendant dire ce que fait le premier appui, c'est ainsi qu'ils finissent par se contredire. Tout ce qui n'a pas de paliers garde exactement la règle 3 de la spec 174. Voir specs/178-timed-action-duration-steps/.
179 Un compteur alimenté par un autre réseau La spec 173 déclarait une topologie que l'arithmétique de réconciliation ne voyait pas — un compteur à l'intérieur d'un autre. Voici l'autre : une pince sur un circuit alimenté par un second compteur du fournisseur (le cas qui l'a soulevée : une prise de recharge VE sur un autre abonnement). L'enrôlement étant une liste noire (#523), la pince entre dans toutes les réconciliations contre le compteur principal, et trois chiffres se faussent d'un coup : la répartition affiche une part de 3 kW que le total principal n'a jamais portée, le résidu « Autre » est écrasé à 0, et la spec 123 facture au tarif principal les kilowattheures d'un autre réseau. Même principe de conception que la 173 — déclarer ce qui est vrai du tableau électrique, pas une case « masquer » : Equipment.separateSupply dit que le compteur pend d'un autre réseau, et les deux surfaces (répartition par usage et donut en direct spec 117) l'affichent à part — son propre groupe, séries brutes, en kWh seulement, jamais en € — tandis que sa carte, son historique et ses graphiques ne bougent pas. Refusé sur le compteur principal et les types de production (la référence ne peut pas être hors d'elle-même), et un compteur sur alimentation séparée ne peut pas être parent spec 173 — rien de ce que la répartition affiche ne peut être « dans » un compteur d'un autre réseau ; une déclaration d'imbrication qui pointe dessus est conservée mais simplement inutilisée, si bien que retirer le drapeau restaure la soustraction telle quelle. L'agrégation de zone (spec 170) reste volontairement brute : le garage tire réellement ces watts, quel que soit le compteur qui les facture. Voir specs/179-separate-supply-meter/.

Comment utiliser cet index après une perte de contexte

  1. Trouvez le thème dont vous avez besoin via les en-têtes de section ci-dessus
  2. Ouvrez specs/XXX-name/spec.md pour les exigences et critères d'acceptation
  3. Ouvrez specs/XXX-name/architecture.md pour le design technique, les changements de modèle de données, l'impact au niveau fichier
  4. Ouvrez specs/XXX-name/plan.md pour les étapes d'implémentation

Pour l'architecture actuelle basée sur les plugins, commencez par la spec 053 (PackageManager), c'est la racine de tout ce qui touche aux plugins.

Pour l'auto-update, commencez par la spec 060, elle remplace la spec 057 et est le design actuel.

Pour la vue d'ensemble du système, voir technical/architecture.md.

Pour l'exploitation production (déploiement, backup, auto-update, logs), voir technical/deployment.md.