# Release process av-tools is licensed GPL-3.0-or-later. A publishable release is the exact reviewed source tag, production ZIP/checksum, Corresponding Source and third-party notices distributed together. The steps below fail closed where practical. ## 1. Resolve legal/source identity The repository already declares the application licence and immutable third-party source identities. Before any distribution: 1. commit the reviewed GPL-3.0-or-later source; 2. create and verify annotated tag `v0.2.1` at that exact commit; 3. push the commit and tag to the canonical public repository; 4. assemble, review and publish corresponding source and exact external notices for both reviewed core profiles and linked libraries; 5. keep the manifest/package metadata, `SOURCE.md`, ZIP and tag version aligned. `SOURCE.md` pins FFmpeg, ffmpeg.wasm, x264 and LAME by full commit. Do not describe the complete bundle as MIT-only. ## 2. Reproducible checks With Node 22+ and the lockfile: ```sh npm ci npm run fixtures:verify npm run check npm run test:browser ``` `check` verifies manifest/vendor assets, types, lint/format, unit tests, production build and `toolbox-check dist`. Browser tests must exercise ST, MT, ST fallback, cancellation/recovery, nested paths and no runtime CDN request. Record exact results in the release report. ## 3. Package Normal packaging validates the root GPL version 3 text and matching `GPL-3.0-or-later` package/manifest metadata: ```sh npm run package:release npm run source:package npm run vendor:verify ``` The legacy development-only escape hatch is retained only for checking an otherwise unlicensed temporary fixture: ```sh npm run package:release -- --allow-unlicensed-development-smoke ``` Pass `--force` only to replace the exact same-version ZIP and sidecar. Output: ```text release/av-tools-0.2.1.zip release/av-tools-0.2.1.zip.sha256 release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz.sha256 ``` Verify independently: ```sh node scripts/checksum-release.mjs (cd release && sha256sum -c ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz.sha256) unzip -l release/av-tools-0.2.1.zip tar -tJf release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz ``` The packager: - rejects symlinks, special files, traversal, absolute/ambiguous/duplicate archive paths and credential-like files; - rejects source maps and local absolute paths in text release files; - requires entry, manifest, icon and every declared asset; - requires root `CHANGELOG.md`, `SOURCE.md`, `THIRD_PARTY_NOTICES.md`, `LICENSES/`, `assets/` and `vendor/`; - adds installed runtime npm licence files; - sorts paths, stores files as mode 0644, uses 1980-01-01 00:00:00 UTC and produces deterministic ZIP32 bytes; - excludes `node_modules`, test fixtures and source because it starts from `dist` plus an explicit legal/document list. When used against a fixture without an application licence, the escape hatch adds `DEVELOPMENT-ONLY-NOT-FOR-DISTRIBUTION.txt` inside the ZIP. ## 4. Portal assembly smoke Use a reviewed Portal Git repository beside av-tools. The harness reads its exact `HEAD` and clones that revision into a temporary directory: ```sh npm run portal:smoke -- \ --artifact release/av-tools-0.2.1.zip \ --portal-root ../toolbox-portal ``` The smoke harness clones the exact Portal HEAD to a temporary directory, copies the ZIP there, writes a temporary one-app lock derived from `release/toolbox.lock.example.json`, runs `npm ci`, tests, build and assembly, then verifies the generated catalogue/release records and copied FFmpeg assets. The temporary directory is removed unless `--keep-temp` is explicitly passed. No machine-specific path is committed and no Portal worktree is changed. Portal `v0.6.0` (`5c052bc6d1073a66600cfddc44c0e16da34bede8`) already passes the isolation, Blob-media CSP and explicit WASM MIME checks. Its plain-semver cache rule does not match the reviewed core's build-profile suffix, so the harness reports a cache warning. The staged Portal extension accepts only the exact reviewed profile in addition to plain semantic versions and rejects malformed or mutable-looking suffixes; a temporary clean commit containing that patch passed this smoke without warnings. `--allow-known-header-gap` remains available only for deliberately testing an older Portal revision with a known required-header error. It is unnecessary for `v0.6.0` and must not suppress review of new gaps. See `docs/PORTAL_REQUIREMENTS.md`. ## 5. Publish only reviewed bytes From a clean `v0.2.1` checkout, rerun all checks, create the ZIP once, verify the sidecar, assemble that exact ZIP through Portal, and publish the immutable ZIP, `.zip.sha256`, manifest, changelog, Corresponding Source and notices. Put its exact lowercase digest/version/id/target in a reviewed Portal lock. Never use mutable “latest” URLs or credentials in a lock. The final report must state inspected commits, exact packages/build config, capabilities, completed tested milestones, all check results, artifact paths, Portal result, fixture provenance, licence status, headers, gaps, performance and browser limits. A UI or command builder alone is not a completed milestone.