Serve a per-node-type manifest alongside the shared one #82
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/per-type-manifest"
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?
CCS-UHA-24. Firmware side (CCS-UF-20) moves a node onto
/firmware/manifest/0x<type>.jsoninstead of downloading the whole shared manifest, because the fleet's entry count now exceeds the node's 2048-byte buffer.Routes the new path in
updater/file_server.py: a bare object with the same four members already generated per entry, noimageswrapper, matched with a strict0x+ two lower-case hex digits pattern (anything else 404s). A node type with nothing cached gets a genuine 404. The shared/firmware/manifest.jsonkeeps serving unchanged, for firmware that still asks for it. Guarded at 512 bytes, matching the node's smaller buffer for this path (firmware_manifest.h).Tested: new cases cover the per-type file, the 404 for an unpublished type, the bare-object body, lower-case-only matching, a malformed type 404ing, the body staying under 512 bytes, and the shared manifest still working. Full suite and
ruffpass.Implementation checks out against every requirement: lower-case-only regex (
fullmatch, noIGNORECASE), bare 4-member body, 512-byte guard distinct from the shared 2048, genuine 404 for an uncached type and for a malformed segment, shared/firmware/manifest.jsonroute untouched, traversal defence stays structural (looked up via theadvertiseddict, never joined to the filesystem). Diff is minimal,manifest_body/offersuntouched. Tabs, British spelling, comments carry rationale rather than restating code. Full suite (1177 passed) andruff check/format --checkare clean on this branch.Two minor test gaps, neither blocking:
tests/test_node_file_server.py::test_the_per_type_manifest_path_matches_lower_case_only— theupper_digitcase (/firmware/manifest/0x1A.json) doesn't actually exercise digit-level case folding. Node type0x1Ais never cached in the test, so it 404s via "type not found" regardless of whether the regex were case-sensitive on hex digits — a regression to[0-9a-fA-F]would slip through this assertion unnoticed. Only theupper_prefixcase (0X12, where0x12/bathroom is cached) is a genuine regression test. Worth caching an image with a hex-letter type and asserting0x1a.jsonis 200 while0x1A.jsonis 404, or dropping the misleading half.type_manifest_body's over-512-bytes warning branch (updater/file_server.py:119-125) is the one uncovered line in the file — no test exercises it, unlike the shared manifest's equivalent (test_a_manifest_a_node_would_refuse_is_warned_about).Round 2: both round-1 gaps are properly closed.
node_underfloor(0xA0) and requests0xA0.json, so it's a real regression test — verified by mutating the regex tore.IGNORECASE, which makes it fail as expected.test_a_type_manifest_a_node_would_refuse_is_warned_aboutexercises the >512 branch intype_manifest_bodydirectly — verified by removing the warning branch, which makes it fail. BuildingCachedImageby hand is consistent with the existingimage()helper pattern intests/test_firmware_versions.py, and is the right call here since the real HTTP path can never reach 512 bytes (image paths are capped at 63 byMAX_IMAGE_PATH, well under what's needed).Full suite (1178 passed, 3 skipped) and
ruff check/ruff format --checkboth clean.updater/file_server.pyis at 100% coverage. No further issues — clean.