feat: publish drivers with the control path they were ported with#31
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 36ab10190b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # A driver that declares read_only in its own DRIVER table overrides | ||
| # this: a meter saying what it is outranks an entrypoint it may only | ||
| # have inherited from a shared source. | ||
| controls = has_driver_command and not declares_read_only |
There was a problem hiding this comment.
Keep unapproved control paths disabled
When the full channel is built, deriving controls solely from the presence of driver_command enables drivers that have not passed the control gate: Pixii's package explicitly sets FTW control_enabled to false and says physical HIL is still pending, while AlphaESS's matching function only logs “control not yet implemented” and returns false. The resulting signed entries nevertheless advertise control and receive write permissions, so require explicit target approval/HIL rather than treating every legacy entrypoint as accepted control.
AGENTS.md reference: AGENTS.md:L15-L18
Useful? React with 👍 / 👎.
directManifestRuntimePolicy refused any device-drivers artifact that was not read-only, and the channel marked every one of them read-only. Meanwhile the bundled copy -- a pinned snapshot of the same repository since #673 -- carries no policy at all and drives batteries fine. One source file, two behaviours, decided by where the file came from. A driver the channel publishes with control_enabled now gets no runtime policy, which is exactly what the bundled copy of that same source already gets. A driver that declares itself read-only still gets a read-only policy bound to its signed identity and permissions. read_only and control_enabled are two spellings of one fact, so a manifest where they agree with each other -- both true or both false -- is refused: a driver that may control while claiming to be read-only reads as safe to anything that checks only one of them. Pairs with srcfl/device-drivers#31, which stops making artifacts write-inert. This side has to reach the field first, or a gateway on an older build refuses to load an updated driver from the channel. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every artifact this channel published was write-inert. The generator replaced host.modbus_write, host.mqtt_pub and the rest with a function that raises, then overwrote driver_command and driver_default_mode after the source loaded. All 80 drivers went out as read_only, control_enabled false. The bundled copy has none of that, and since FTW #673 it is a pinned snapshot of this repo. So one source file could drive a battery when it shipped with the build and could not when it was downloaded -- the same code, two behaviours, decided by where the file came from. The manifests could not be trusted to sort this out: 16 of 18 battery drivers carry a working driver_command while their catalog manifest still says control: false. The control logic was ported and the manifest never caught up. So the code decides. A driver whose source defines driver_command is published with that path intact and gets the write permission for its protocol. A driver that declares read_only in its own DRIVER table keeps the guards -- that is a meter or a telemetry gateway stating what it is, and it outranks an entrypoint the driver may only have inherited from a shared source. Today that is 43 controlling and 37 read-only, with sdm630, zap and the esphome meters staying read-only exactly as before. The manifest now carries read_only and control_enabled as opposites of one fact, and verification rejects them when they disagree: a driver that may control while claiming to be read-only reads as safe to anything that checks only one of the two. A read-only driver with a write permission is rejected for the same reason. The signed identity is still reasserted after the source loads, so no driver can rename itself into another driver's slot. Closes #30 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
36ab101 to
3f0171d
Compare
…rol (#676) directManifestRuntimePolicy refused any device-drivers artifact that was not read-only, and the channel marked every one of them read-only. Meanwhile the bundled copy -- a pinned snapshot of the same repository since #673 -- carries no policy at all and drives batteries fine. One source file, two behaviours, decided by where the file came from. A driver the channel publishes with control_enabled now gets no runtime policy, which is exactly what the bundled copy of that same source already gets. A driver that declares itself read-only still gets a read-only policy bound to its signed identity and permissions. read_only and control_enabled are two spellings of one fact, so a manifest where they agree with each other -- both true or both false -- is refused: a driver that may control while claiming to be read-only reads as safe to anything that checks only one of them. Pairs with srcfl/device-drivers#31, which stops making artifacts write-inert. This side has to reach the field first, or a gateway on an older build refuses to load an updated driver from the channel. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The channel refuses to republish a driver whose artifact bytes moved without a higher version, and #31 moved all eighty: the generated prefix changed for every driver, and forty-three stopped carrying write guards. Gaining a control path is a behaviour change, so those forty-three take a minor. The rest only lost a comment line and take a patch. esphome-dsmr, pixii and sungrow repeat their version inside their own DRIVER table, so those had to move in step with the manifest. Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Closes #30.
Every artifact this channel published was write-inert. The generator replaced
host.modbus_write,host.mqtt_puband the rest with a function that raises, then overwrotedriver_commandanddriver_default_modeafter the source loaded. All 80 drivers went outread_only: true,control_enabled: false.The bundled copy has none of that, and since FTW #673 it is a pinned snapshot of this repo. The same source file could drive a battery when it shipped with the build and could not when it was downloaded.
The manifests were not the answer either
driver_commandcontrol: falseThe control logic was ported. The manifest never caught up. Deriving control from the manifest would have published pixii, alphaess, solaredge, sma and eleven others unable to do the one thing they were ported for.
So the code decides
driver_commandis published with that path intact, and gets the write permission for its protocol (modbus.write,mqtt.publish, …).read_onlyin its own DRIVER table keeps the write guards. That is a meter or a telemetry gateway stating what it is, and it outranks an entrypoint the driver may only have inherited from a shared source.Today: 43 controlling, 37 read-only.
sdm630,zapand the esphome meters stay read-only exactly as before.Consistency is enforced, not assumed
read_onlyandcontrol_enabledare two spellings of one fact, and verification now rejects them when they disagree — a driver that may control while claiming to be read-only reads as safe to anything checking only one of the two. A read-only driver carrying a write permission is rejected for the same reason.The signed identity is still reasserted after the source loads, so no driver can rename itself into another driver's slot.
Paired change
FTW must stop refusing these:
directManifestRuntimePolicyreturned an error for any device-drivers artifact that was not read-only. That is srcfl/ftw — a controlling driver now gets no runtime policy, so it runs under the same terms as the bundled copy of the same source.Merge order matters: the FTW change should land and reach the field first, or a gateway on an older build will refuse to load an updated driver from this channel.
1984 tests pass.
🤖 Generated with Claude Code