Files
ESP32_Serial_Swiss_Army_Knife/docs/release_packaging.md
T
Commander1024 797d2681ac Migrate to IDF 5.5.3 candidate
Pin PlatformIO packages and toolchains, rebase protected SDK
overrides, and add WebSocket receive regression coverage. Document
isolated candidate validation, archive provenance, and remaining gates.
2026-09-18 14:23:13 +02:00

16 KiB

Offline release notice packaging

This procedure produces a bounded notice/provenance bundle, not a firmware release, corresponding-source archive, complete SBOM, or legal clearance. The radio-blob corresponding-source/System Library question remains open. See the license inventory for the original review and the retained scope/provenance statement for license choices, mixed notices, wolfSSH packaging discrepancy, TLSF text assembly, icon limits, and remaining release gates.

Run against the installed reviewed snapshot

Requirements: Python 3.9+ on Linux/POSIX with O_NOFOLLOW, directory descriptors and dir_fd operations; already installed matching managed components, ESP-IDF and Xtensa toolchain. Standard library only. The tool never fetches, installs, builds, runs PlatformIO, accesses a device, or regenerates assets.

Run from the repository root. Supply an explicit, not-yet-existing output directory outside all three input roots, with an existing parent. Example for the reviewed installed 5.5.3 candidate (choose a fresh final directory name):

python3 tools/release_notices.py \
  --sdk-root /home/mscholz/Repos/ESP32_serial_swiss_army_knife/.pio/idf-candidate-5.5.3/core/packages/framework-espidf \
  --toolchain-root /home/mscholz/Repos/ESP32_serial_swiss_army_knife/.pio/idf-candidate-5.5.3/core/packages/toolchain-xtensa-esp-elf \
  --output /tmp/esp32-release-notices-review-01

--project-root optionally selects a different checkout containing the exact reviewed inputs; by default it is the script's repository. The trusted catalog always comes from the script's repository, not from that alternate checkout. Paths to SDK/toolchain packages are explicit; no installation is guessed. There is no user catalog option, force/overwrite mode, automatic repinning, recursive collection, archive command, or automatic release upload.

Every input in third_party/release-notices/inputs.json is mandatory and pinned by full-file SHA-256 and size. Missing sources, altered bytes, bad excerpts, empty files, directories, FIFOs, symlinks (even to identical files), parent traversal, binary notice payloads and exhausted bounds fail closed. Symlinks in input-root or output-parent ancestry are rejected too: pass real non-symlinked paths, not a convenience symlink. All input preflight completes before creating output. The limits are 128 inputs, 4 MiB per input/catalog and 32 MiB cumulative source bytes. The current catalog has 75 inputs, including the retained SVGs and pinned icon provenance evidence. Overview documents edited in this integration are not catalog inputs; docs/icon_provenance.md is pinned. Coordinate any change to that record with the catalog owner; never silently repin.

An existing output file, directory (even empty) or dangling symlink is never overwritten. Parent directories are not automatically created. Output uses private directory/file modes (0700/0600, subject to umask). On a write failure, the tool deliberately leaves any partial directory for inspection and never recursively deletes it. A successful exit plus a valid manifest and matching payload hashes is required; presence of a partial manifest is not success. Use another fresh path for a retry. Do not put output into a tree that an untrusted process can concurrently rename or modify; descriptor/no-follow checks prevent symlink traversal but are not isolation from the same OS user.

Bundle layout and reproducibility

  • README.txt: limitations and entry point for recipients.
  • inputs/project/…: project GPL text, resolved lock, managed licenses and manifests, wolfSSL/wolfSSH README evidence, original wolfSSH header excerpts, xterm MIT texts and recorded provenance, icon summary and official 7.4.47 SVG/license/metadata evidence, TLSF full rendering and scope/provenance statement.
  • inputs/sdk/…: complete scoped SDK license documents, mixed Newlib/argtable3 notices, radio license files, package/version identity and original source notice excerpts. SDK LICENSE supplies full Apache-2.0 text; it does not authenticate individual icons or cover all SDK files.
  • inputs/toolchain/…: actual toolchain Newlib text, GPLv3, GCC Runtime Library Exception 3.1 and package identity. No toolchain executable is copied.
  • manifest.json: schema/snapshot, catalog SHA-256, logical root/path, full-source size/hash, optional zero-based half-open byte range, purpose, output path/size/hash, and the generated introduction's hash. Excerpts have .notice.txt appended; null ranges retain whole original files unchanged.

Whole mixed documents are preserved, not converted into guessed SPDX labels. The longer toolchain Newlib notice does not replace the distinct SDK text. The wolfSSH package GPLv2-or-later text and GPLv3-or-later source headers remain separate and unmodified; upstream packaging clarification is still needed.

Generated metadata contains no collection timestamps or absolute host paths; original notices retain their own dates and text. For identical catalog and inputs, file names and file contents are deterministic across output locations, input-root locations and source mtimes. Directory/file mtimes are not normalized, and no reproducible tar/zip archive is claimed. The manifest hashes all payloads but not itself; retain its hash in your separate release evidence if needed. The catalog is trusted reviewed policy, not a cryptographic signature or proof of package-wide integrity/authorship.

Only explicit catalog paths are read. No application config, sdkconfig, build tree, ELF/map/binary, key, credential backup, NVS/flash dump or whole repository is collected. Hash-pinned source implementations are read only to validate original header excerpts, not copied as implementations. The lock and installed package/component manifests are dependency identity metadata, not build configuration. A hash pin is not a general-purpose secret scanner: review additions to this trusted list before accepting them.

Validate and inspect

Temporary-fixture regression suite (does not need installed packages):

python3 tests/release_notices/run.py

The suite tests missing/changed sources (including changes outside a notice excerpt), exact mixed-text retention, byte ranges, path traversal, source/root/ output symlinks, existing user data, nonregular files, bounds, output failures, secret/config exclusion, determinism, and CLI behavior. No hardware tests are implied.

For a real bundle, check the successful process exit, parse manifest.json, recompute every payload hash/size, check no unlisted files are present, and read the scope statement. Compare two independently created fresh outputs by relative names and bytes (not mtimes). Inspect at least both Newlib files, argtable3, wpa_supplicant COPYING/README, GCC exception, wolfSSH LICENSE/README and header excerpts, TLSF text/provenance, both xterm notices and the icon summary. These checks establish scoped assembly, not release compliance.

If a pinned input differs, stop and review the changed package/license/source. There is deliberately no update-catalog command. Review versions, new/nested NOTICEs, original source notice ranges and hashes, then deliberately update catalog policy and test it. The runtime does not discover added notices or packages outside its finite list; this limitation makes its reads bounded and prevents opportunistic collection of user files.

Supplied execution evidence — 2026-09-16

Agent results: 36 notice fixture tests PASS, and two actual 75-input bundles verified deterministic, each 77 files / 4,433,930 bytes. These replace the earlier 62-input / 64-file / 541,147-byte snapshot, not its historical record. No parent rebuild or bundle reassembly was run in this documentation turn; firmware source is unchanged. Assembly is not legal clearance or Phase 9 acceptance. The unfixed Wi-Fi blocker also remains a separate security gate; a future coherent vendor update requires catalog review.

Installed candidate notice rebase — 2026-09-18

This addendum audits the existing 75-input catalog against already installed PlatformIO 6.13.0 migration candidates, not merely downloaded archives. No installation, build, production/config edit, or security-override rebase was performed by this notice audit. The preceding 2026-09-16 evidence is historical.

Actual candidate package root: /home/mscholz/Repos/ESP32_serial_swiss_army_knife/.pio/idf-candidate-5.5.3/core/packages/. Its framework-espidf/package.json reports 3.50503.0, and version.txt reports 5.5.3. Both toolchain-xtensa-esp-elf/package.json and toolchain-riscv32-esp/package.json report 14.2.0+20251107. RISC-V identity was checked for context; it is not a new input root or a claim of RISC-V notice coverage. The shared /home/mscholz/.platformio/packages/ still contains framework 3.50500.0 / IDF 5.5.0 and both toolchains 14.2.0+20241119; do not use those shared paths with this rebased catalog.

All 75 old catalog full-file hashes/sizes matched the old shared SDK/toolchain and current project inputs before editing. Comparison against the installed candidate found exactly nine changed entries (eight SDK, one Xtensa), listed below. The other 66 entries remain unchanged, including all 39 project/managed inputs, the dependency-lock pin, icon evidence and managed version map. No catalog paths, purposes unrelated to version identity, or excerpt ranges were added/removed/relaxed. Snapshot identity/date and the three identity-purpose strings were updated deliberately, not by automatic repinning.

Paths below are relative to the indicated catalog root. Hashes are full-source SHA-256; old hashes remain in the preceding Git catalog revision.

Root / path Old → candidate bytes Candidate SHA-256
sdk / components/esp-tls/esp_tls_mbedtls.c 50176 → 54323 edc39052244526cb91c93a16bc765194031060e5560fd432e75542f2f6c8db53
sdk / components/esp_http_server/src/httpd_parse.c 42937 → 42937 db7fbbb322bccb4a21bc1607208a6bb7d1f4c0d7ecc3299de10c9e60edaa943b
sdk / components/esp_https_server/src/https_server.c 15257 → 15459 a2a5ca0549fbe8d1ddd7f9647a48a31fdd6329b997e1550ab69d6a10efecff0d
sdk / components/freertos/FreeRTOS-Kernel/include/freertos/task.h 133072 → 133108 8b908b964d2c87377838762478253eec04312b985e6bb680bacd3f03ab253897
sdk / components/mbedtls/mbedtls/library/ssl_tls.c 329921 → 336963 0154e70f20b465213d3f97a9c2b75e686d79ee83592f90e1d7e7d995593ca7e1
sdk / components/mbedtls/mbedtls/library/x509_create.c 19803 → 19934 55edce5b8fcb039a404b84ea830f06d018128b155dfbf0d74d26b17247b546c6
sdk / package.json 536 → 536 230c52993499adf9f64d1d6477495ea46c3f14d63022bd52081858373098da68
sdk / version.txt 5 → 5 b473c8e2ed91b38d7e96e54d4ce094474ca6015c0641b7cdfc0ab94b1f8b4668
toolchain / package.json 472 → 472 bdd3b852d051d6513912e71d29851bd04b800e2d33d78aec48067af5d83da5c9

Semantic notice review: five changed implementation files retain byte-identical complete opening notices at their existing ranges (ESP-TLS [0,122), HTTPD [0,124), HTTPS [0,123), Mbed TLS shared TLS [0,223) and X.509 [0,169)). Their output hashes stay unchanged; full-source hashes must change even when only implementation bytes change. This does not approve the implementation changes or establish compatibility of the project's security overlays. FreeRTOS task.h retains its complete MIT notice at [0,1455); only SPDX-FileContributor: 2023-2024 becomes 2023-2025 within that excerpt. Its output hash changes from 8e3d9f79bbbdf6dfd6fbf132982a7ec3a45ff6dac92277034316efae4cccad84 to e53c9bcefd4327c713696e870a3568a27cedf8833467b9cd9536cb2e09ab7ad8. The remaining task.h changes correct stack-watermark documentation to bytes. The two package JSON diffs change only versions; SDK version.txt changes only 5.5.0 to 5.5.3.

All 24 remaining SDK inputs and three Xtensa license inputs match the old pins, including SDK/radio Apache texts, both Newlib documents, mixed argtable3, wpa_supplicant and GCC exception/GPL texts. An auxiliary installed-tree filename comparison found the same 45 SDK files whose basenames start with LICENSE, COPYING or NOTICE (case-insensitive), with no additions/removals. All 85 files under Xtensa share/licenses/ have identical relative paths and hashes. This finite discovery check is not an exhaustive attribution or linked-object audit.

Validation after the catalog edit: 36/36 notice fixture tests PASS via python3 -B tests/release_notices/run.py; two fresh temporary actual bundles using the candidate roots above and the current project passed assembly, per-payload manifest SHA-256/size checks, exact file-list checks, and identical relative names/bytes across outputs. Each has 77 files / 4,433,930 bytes (the unchanged total size does not imply unchanged contents). Both manifest SHA-256 values are 1fd0a69b82dc2632bab4ab6dda33675e7229c8d341c7fafb7158c1e8f2456a68. Temporary bundles were removed after comparison. Project entries and managed snapshot pins were also asserted equal to the pre-migration Git catalog.

These results are notice assembly evidence only, not legal clearance, corresponding-source delivery, radio-blob exception approval, vulnerability closure, firmware build validation or target acceptance. Existing pinned project provenance retains historical baseline wording; this addendum distinguishes the new SDK notice snapshot without silently rewriting/re-pinning that evidence. All separate distribution gates below remain open.

Separate work before distribution

  1. Resolve or obtain qualified review of radio-blob corresponding-source or exception basis for the actual linked firmware. Apache binary permissions alone do not settle this question. No legal clearance is claimed.
  2. Resolve the wolfSSH package/header discrepancy and remaining icon derivative questions. Exact retained SVG provenance is verified at official 7.4.47, commit 9e04201d4557e729822fb57f62a316c3dea1d4a8: Google USB and Simran Wi-Fi. Full Apache text is retained; no NOTICE was found in that pinned distribution. Manual firmware bitmap derivation and the distinct mockup Wi-Fi path remain unresolved. No artwork was regenerated.
  3. Audit the final application/bootloader/runtime object set and aggregation boundaries. Full SDK/toolchain redistribution needs broader nested/tool/test notice coverage; this is not an all-files license scanner.
  4. Prepare and validate a separate, deliberately reviewed corresponding-source delivery. Preserve exact required sources and safe build/install inputs, asset preferred sources and scripts, original hash-matching overlay inputs, tools/security_overrides.py, cmake/security_overrides.cmake, root CMake integration, cmake/wolf_crypto_policy.{cmake,h}, and the complete tools/wolfssh_order/ inputs/provenance/archives. Preserve upstream notices and generated dated change notices on eight C sources and one PUBLIC forced header. A stock vendor tarball or this notice bundle is not sufficient. Do not automatically archive the working repository or real configurations.
  5. Assess GPLv3 source delivery/offer and User Product Installation Information. Protect device passwords, Wi-Fi credentials, private keys, verifiers, tickets, credential backups and flash/NVS images throughout that process.
  6. Arrange and verify actual notice delivery with firmware, devices and browser assets. This command does not add a license endpoint, change browser assets, or prove that a recipient of a JS response or standalone device receives notices. Keep these gates open until the real delivery path is validated.