Assigning a Shelly now issues a real broker credential so the physical device can
connect (onboarding was incomplete before):
- MqttCredentialProvisioner writes a mosquitto-compatible PBKDF2-SHA512 ($7$)
password line (in PHP) for username = the device's topic prefix, and touches a
reload trigger. A small wrapper in the mosquitto container (docker/mosquitto/
config/entrypoint.sh) SIGHUPs mosquitto so it re-reads the passwd live — no
restart. Verified: a provisioned device authenticates and publishes to its own
prefix (bound by the pattern %u ACL).
- The credential is shown once on the device page after assignment (enter it into
the Shelly). passwd is app-owned + world-readable so the web request can write it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- AssignDevice derives the Shelly MQTT prefix from the mDNS service instance name
(the device id) instead of the slugified topic identifier (which carries the
_shelly._tcp suffix); non-Shelly devices get no prefix.
- IngestDiscoveryMessage broadcasts DeviceDiscovered only on first creation, not on
every retained/periodic re-publish.
- The generic Confirm modal can target its event at the opening component (->to),
so a shared event name can't be caught by an unrelated component.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Python discovery sidecar (zeroconf mDNS over host network) publishes findings
to homeos/discovery/<source>/<id> as the sidecar user. Compose service with
network_mode: host + NET_RAW. Verified live: it found real devices on the LAN
(a printer and Shellys) via mDNS.
- Listener also subscribes homeos/discovery/#; IngestDiscoveryMessage upserts
discovery_findings (preserving assigned/ignored) and broadcasts DeviceDiscovered
on the private discovery channel.
- "Neue Geräte" page lists findings live with Assign (modal → creates a Device
and links the finding) and Ignore/Restore. Per-device broker credentials are
provisioned at onboarding (noted in the assign hint).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>