Files
ESP32_Serial_Swiss_Army_Knife/docs/release_packaging.md
T
Commander1024 cdc4d4a8df Add Phase 9 validation and advisory review
Record the finite dependency search, Wi-Fi maintenance blocker, and
pinned
icon provenance. Add bounded host orchestration and fixture coverage,
and
update release documentation with current evidence.
2026-09-16 16:26:46 +02:00

10 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 inventory's local installation (choose a fresh final directory name):

python3 tools/release_notices.py \
  --sdk-root /home/mscholz/.platformio/packages/framework-espidf \
  --toolchain-root /home/mscholz/.platformio/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.

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.