Serve firmware images at a path a node can accept #76
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/short-firmware-image-paths"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The manifest advertised the cache tree, 72 characters, and the firmware caps a
manifest
pathat 63 (maxImagePathLength). A longer path fails that entry asthe manifest is parsed, so the node finds nothing for its own type and abandons
terminally — no node has ever issued the image GET, and the bus only carries
SYS_WIFI_STATUSstate 6.Images are now offered at
/firmware/<version>/<environment>.bin, for example/firmware/2026.09.20/node_lighting.bin, 38 characters. The file on disk keepsits name and place; only the advertised path changed, and requests still resolve
against a dictionary of advertised paths rather than being joined onto the cache
root.
Two guards for failures that are silent on the node:
with a warning, rather than offered and rejected by the node it is for.
maxManifestLength) is warned about. It is servedanyway: which node to drop would be an arbitrary choice, and the log is the
only place either fact can surface.
Both warnings fire where the manifest is rendered, not where the offers are
built, so a 404 probe on the LAN cannot repeat them.
Tested by extending
tests/test_node_file_server.py, including a test that pinsthe advertised path length for the longest environment the node registry can
name against the firmware's 63, and one that shows the whole node table
overflowing the manifest cap.
CCS-UHA-20
Three things, none of them in the decode path. The path scheme, the 63 boundary (
>is right: the firmware accepts exactly 63) and the 2048 boundary all matchfirmware_manifest.h, and both guards fail the suite when mutated out.@ -266,0 +265,4 @@2048 bytes, and refuses the whole update over either. An image with too longa path is left out and logged instead of offered. A node finds its own entryby node type, which is byte 0 of the `SYS_ANNOUNCE` it already sends, andchecks the bytes against the hash before it switches boot slot. Only what the manifest offers can be fetched. There isLine left unwrapped at 120 characters; the rest of the paragraph wraps at ~78.
@ -62,0 +83,4 @@One dictionary behind both answers, so nothing is servable that themanifest did not offer. An image a node could not name is left outentirely: offering it would fail the whole manifest for every node."offering it would fail the whole manifest for every node" is not what the firmware does.
parseFirmwareManifestdescends to its own0x..key and skips every other entry withskipValue(), so a too-long path only fails the entry it is in, and only for that node type. Say "fails that node's own entry". The same wording is in the PR body.@ -62,0 +89,4 @@for image in offered(cache):path = image_path(image)if len(path) > MAX_IMAGE_PATH:_LOGGER.warning(This warns on every GET, not once per manifest:
advertised()runs again for each image request and for each unknown path, so any 404 probe on the LAN repeats it. Worth warning only where the manifest is built.7f884b4covers all three. Nothing outstanding.