fix(nibe_local): version the DER correction so the channel can publish it - #55
Merged
Merged
Conversation
…h it
The driver release failed on main with
error: nibe_local: changed artifact needs a higher version than 1.1.0
srcfl#53 corrected the manifest from ders: [meter] to ders: [heatpump] and read
that as catalog-only metadata, so it left the version at 1.1.0. It is not
catalog-only. _load_channel copies ders into the artifact's capabilities and
the channel signs source and metadata as one file, so the correction moved
the published bytes under a version that has already shipped. The channel
refused, and it was right to: that immutability is what lets an operator name
the bytes a site is running.
So nibe_local takes a patch. Patch rather than minor because no register,
field or emitted metric changed -- only the DER the catalog states. The Lua
source is untouched and its sha256 with it, and bump_driver leaves the DRIVER
table alone because the file is byte-identical to its FTW baseline, so the
provenance guarantee srcfl#29 established is spent on nothing.
Verified against the currently published beta manifest: of 80 drivers exactly
one differs from what is published, and after the bump nothing is blocked.
CONTRIBUTING said to raise the version whenever the Lua source changes, which
is what srcfl#53 followed. It now also names the manifest fields that reach the
signed artifact -- ders, protocol, and a tested_devices manufacturer and
model_family -- and warns that this check runs on main after the merge rather
than in the pull request, because only the release can read the channel.
Signed-off-by: Hugo Karlsson <48095810+HuggeK@users.noreply.github.com>
Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
HuggeK
marked this pull request as ready for review
July 31, 2026 09:12
This was referenced Jul 31, 2026
HuggeK
added a commit
that referenced
this pull request
Jul 31, 2026
…o unlock it protocol names a transport and answers neither question an owner asks first. nibe_local and myuplink are both protocol: http and both read a NIBE heat pump, and they are opposites: one reads the pump over the LAN, the other reads NIBE's cloud. The catalog could not tell them apart. Two fields, orthogonal to protocol rather than folded into it. Splitting protocol into http_local/http_online was the obvious move and the wrong one: protocol feeds PROTOCOL_PERMISSIONS, so new values change what a package build grants, and it does not generalise -- MQTT can be a cloud broker too. connectivity: local | cloud where the driver talks while running setup: [...] what a human must obtain first, and from whom Backfilled across all 80 drivers from what the sources do. 77 local, 3 cloud: myuplink, easee_cloud and tibber are the only drivers that hardcode a vendor endpoint. Every other HTTP driver builds its base URL from config, and the Modbus, MQTT and serial drivers name a vendor only as homepage. setup is the second axis, and a driver can be local and still locked until somebody unlocks the interface: nibe_local is enabled in the pump's own installer menu -- no app, no account -- while sonnen and CTEK are enabled in the device's web UI, sma_pv needs an installer, and eight drivers need a bridge in between. 17 have a recorded gate; 63 do not, and absent means unrecorded. The page renders that as "Not recorded", never "Nothing to set up", and only setup: [none] claims a device needs nothing but an address. tests/test_connectivity.py stops connectivity being decorative. A cloud endpoint must be hardcoded -- there is nowhere else for it to come from -- while a LAN address comes from config, so the test reads that asymmetry in both directions and separates exactly the three from the other 77. Neither field reaches the signed artifact: _load_channel copies an explicit allowlist and these are not in it. So no driver version moves, unlike the ders correction in #53 that #55 had to version. Signed-off-by: Hugo Karlsson <48095810+HuggeK@users.noreply.github.com> Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The driver release failed on
mainwithNothing shipped, which is the correct outcome.
#53 corrected
nibe_local's manifest fromders: [meter]toders: [heatpump]and read that as catalog-only metadata, so it left the version at1.1.0. It is not catalog-only._load_channelcopiesdersinto the artifact'scapabilities, and the channel signs source and metadata as one file — so the correction moved the published bytes under a version that has already shipped. The channel refused, and it was right to: that immutability is what lets an operator name the bytes a site is running.So
nibe_localtakes a patch, 1.1.0 → 1.1.1.Why a patch and not a minor
No register, field or emitted metric changed — only the DER the catalog states. This follows the precedent in #32, where drivers that gained a control path took a minor because a host could now do something new, and the rest took a patch for a bytes-only move.
The Lua source is untouched and its
sha256with it, andbump_driverleaves theDRIVERtable alone because the file is byte-identical to its FTW baseline — so the provenance guarantee #29 established is not spent on this.Verified
Built the channel entries locally against the currently published beta manifest and compared every artifact digest:
Before the bump that same check reported
nibe_localblocked, reproducing the release failure exactly.nibe_localis the only driver that differs from what is published — the release stops at the first offender, so this confirms there is no second one waiting behind it.Other checks run
validate_manifest.py— 80 manifests, 0 errorsgenerate_index.py,generate_devices.py,generate_support_status.py— regenerated and idempotent;sync_manifests.py --id nibe_localreports the manifest matches its sourcegenerate_history.py --check— driver history intacthost_api_check.py --check,check_public_boundary.py— passpytest drivers/tests tests— 2947 passed. Four modules needing thepackageextra (cryptography) were skipped, and 10 tests fail identically on the unmodified base commit: they need thelua55interpreter the Makefile builds, plus one Windows path-handling issue intest_blueprint.py. Nothing here is affected by this change; CI runs all of them.The trap that caused it
CONTRIBUTING.mdsaid to raise the version whenever the Lua source changes, which is exactly what #53 followed. It now also names the manifest fields that reach the signed artifact —ders,protocol, and atested_devicesmanufacturerandmodel_family— and warns that this check runs onmainafter the merge rather than in the pull request, because only the release job can read the channel.Possible follow-up, deliberately not in this PR
The gap is structural: a PR that edits one of those manifest fields merges green and breaks the release afterwards. A pre-merge job could download the published
manifest.jsonand run the same comparison — it needs only the public key, which is already in the workflow env and not a secret. That is a new check rather than a fix to this failure, so it is left out here.The
CHANGELOG.mdentry from #53 is amended in the same commit: it claimed the version and the published bytes were untouched, and half of that is no longer true.