feat: publish av-tools 0.2.0

This commit is contained in:
2026-07-27 01:04:21 +02:00
parent fcc537b024
commit 0a4548851c
68 changed files with 4130 additions and 605 deletions

View File

@@ -1,13 +1,13 @@
# FFmpeg WebAssembly build record
av-tools ships the published ESM assets from `@ffmpeg/core` and
`@ffmpeg/core-mt` **0.12.10**. The browser wrapper is `@ffmpeg/ffmpeg`
**0.12.15** and helpers are `@ffmpeg/util` **0.12.2**. All versions are exact,
not ranges.
av-tools ships the locally rebuilt, reviewed core profile
`0.12.10-reviewed-stack5m.1` in single-thread and multithread forms. The
browser wrapper is `@ffmpeg/ffmpeg` **0.12.15** and helpers are
`@ffmpeg/util` **0.12.2**. All versions and build inputs are exact, not ranges.
## Underlying build
The matching ffmpeg.wasm upstream release is `v12.15` at
The base ffmpeg.wasm upstream release is `v12.15` at
`71aa99d37c02a7b4c435275ca9ef50e612f6efa1`. Its Dockerfile selects:
- FFmpeg **n5.1.4** (libavcodec 59.37.100);
@@ -15,6 +15,14 @@ The matching ffmpeg.wasm upstream release is `v12.15` at
- production `-O3 -msimd128`;
- pthread flags for the MT build and explicit thread disabling for ST.
The reviewed profile then applies upstream ffmpeg.wasm commit
`b409e36475bc21f0451b5b1e1d126fa82871439a` to select a 5 MiB Emscripten stack.
That upstream fix addresses the libopus zero-byte/out-of-bounds failures
reported in issues `#591` and `#775`. The local driver additionally makes the
upstream container-stage dependency isolation explicit, disables native x265
assembly for the wasm32 build, bounds parallel jobs and refuses output that
contains the maintainer's repository or SDK paths.
The build configuration embedded in both copied WASM files is:
```text
@@ -35,8 +43,8 @@ The build configuration embedded in both copied WASM files is:
--cxx=em++
--objcc=emcc
--dep-cc=emcc
--extra-cflags='-I/opt/include -O3 -msimd128'
--extra-cxxflags='-I/opt/include -O3 -msimd128'
--extra-cflags='-I../../../../install/include -O3 -msimd128'
--extra-cxxflags='-I../../../../install/include -O3 -msimd128'
--enable-gpl
--enable-libx264
--enable-libx265
@@ -76,16 +84,26 @@ respective branch tips. `SOURCE.md` records retrieval commands.
| Mode | File | Bytes | SHA-256 |
| ---- | -------------------------- | -------: | ------------------------------------------------------------------ |
| ST | `st/ffmpeg-core.js` | 111804 | `67a48f11645f85439f3fde4f2119042c16b374b910206b7a7a24f342e28dcae3` |
| ST | `st/ffmpeg-core.wasm` | 32232419 | `9f57947a5bd530d8f00c5b3f2cb2a3492faa7e5d823315342d6a8656d0a6b7b7` |
| MT | `mt/ffmpeg-core.js` | 128947 | `270a2e6ff945e173238610669a3f7132df5f9c52698a9bf708cf5c2ab6bda0de` |
| MT | `mt/ffmpeg-core.wasm` | 32718323 | `be2c97605366b78f3f13e21b52e81a55a79e1f29c133b03a68ec187b1a2ec41a` |
| ST | `st/ffmpeg-core.js` | 111804 | `80c05d79d0e4e9434977b76cb851d10ddf2bfd378570178700d2c43b8afdcb24` |
| ST | `st/ffmpeg-core.wasm` | 32232580 | `fe41ddc77220cef6c04f5d48eeffcaaaef179ad270642e098f9945013aa0c9dc` |
| MT | `mt/ffmpeg-core.js` | 128953 | `4f2650099ab70cb2583951c0421147c62bea6c18dfbba5cfae4d7698b5d0ab62` |
| MT | `mt/ffmpeg-core.wasm` | 32718455 | `abbead010cb0448b26f01a36a3c8c03a6b04aca07812ddd4719a7f4b6bf4b645` |
| MT | `mt/ffmpeg-core.worker.js` | 2115 | `f77898d631dc010b45c29c23cb4379c611a7d7b131bf591d08a656bb729a4ca3` |
`npm run vendor:ffmpeg` copies these files from `node_modules` to
`public/vendor/ffmpeg/0.12.10/`; `npm run vendor:verify` checks versions,
sizes, paths and digests. Vite then copies them unchanged into `dist`. A normal
production build performs no network download.
The deterministic five-file repository artifact is 21,338,974 bytes with
SHA-256
`ebc068c6d096de55ae3335b04b7121130665f5b0ffa7a828067122733f55185f`.
`npm run vendor:ffmpeg` verifies and unpacks the deterministic tracked core
artifact to
`public/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/`;
`npm run vendor:verify-runtime` checks the build profile,
source/toolchain/patch identity, tracked artifact, generated paths, sizes and
digests without requiring a release-directory download. The stricter
`npm run vendor:verify` release gate also hashes the build-qualified
Corresponding Source archive. Vite then copies the verified bytes into `dist`.
A normal production build performs no network download and cannot fall back
to the older published npm core bytes.
## Multithread Chromium guardrail
@@ -118,26 +136,42 @@ This is a conservative browser-memory guardrail, not a guarantee that sixteen
large jobs or three large contact sheets fit in memory. Cancellation and
failed filesystem-cleanup recovery continue to recreate the core immediately.
## Opus regression risk
## Opus regression evidence
Pinned core 0.12.10 predates upstream ffmpeg.wasm fixes associated with stack
size and Opus zero-byte/out-of-bounds failures (including upstream issues
`#591` and `#775`). Therefore:
Published core 0.12.10 predates the upstream stack-size fix and stalled in the
real Opus preset path even though it advertised the `opus` muxer and
`libopus` encoder. Capability discovery alone was therefore not accepted as
enablement evidence.
- decoder/encoder listing is not enough to certify Opus;
- real ST and MT fixture encodes must produce a non-empty, re-probeable output;
- the Opus audio and VP9/Opus presets must remain disabled with a diagnostic
if that smoke fails;
- a core upgrade requires new checksums, capability snapshots, legal review
and regression tests.
On 2026-07-26 the Chromium harness used the checked
`tests/fixtures/generated/tone.wav` fixture (32,102 bytes, SHA-256
`0fd1f54d6be2f1cc7fd778775dd29cf184770d3716cf3394bf03ed54ac264c3c`)
and the real built-in `audio-opus` preset/command planner. After rebuilding
with the reviewed stack profile, the isolated ST and MT runs each:
This is a known pinned-core risk, not a claim that every Opus job fails.
- loaded the requested mode rather than a fallback;
- mapped PCM audio to `opus (libopus)`;
- opened the declared Opus output and reported its libopus encoder;
- returned non-empty bytes within its independent containment limit;
- re-probed the result as positive-duration Opus audio.
```sh
# Record JSON evidence.
npm run evidence:opus
# Positive Opus enablement/release gate.
npm run test:opus-regression
```
The Opus audio and VP9/Opus presets are enabled only when the reviewed-core
lock records both passing modes and runtime discovery finds every preset
requirement. This is exact Chromium fixture evidence, not a claim about every
browser, input or possible Opus build.
## Licence consequence
The core packages declare GPL-2.0-or-later and the actual build enables GPL and
links external codecs. The wrapper/util are MIT. av-tools is
GPL-3.0-or-later, and the distributed application must not be described as
MIT-only. Publish the reviewed Corresponding Source and external notices with
the binary release. See `LICENSE`, `LICENSES/`, `THIRD_PARTY_NOTICES.md` and
`SOURCE.md`.
The actual core build enables GPL and links external codecs. The wrapper/util
are MIT. av-tools is GPL-3.0-or-later, and the distributed application must
not be described as MIT-only. Publish the reviewed Corresponding Source and
external notices with the binary release. See `LICENSE`, `LICENSES/`,
`THIRD_PARTY_NOTICES.md` and `SOURCE.md`.

View File

@@ -5,7 +5,7 @@ extensions or this document. The app queries muxers, demuxers, decoders,
encoders and filters; a preset is disabled with missing components listed.
Browser playback is a separate capability checked with MIME/media APIs.
## 0.1.0 candidate fixture matrix
## 0.2.0 release fixture matrix
All 15 files are generated and re-probed with native FFmpeg 7.1.3 for test
preparation and pass the checksum/probe verifier. That proves fixture
@@ -41,20 +41,20 @@ browser may still be unable to preview the result.
Preset availability always depends on detected runtime requirements:
| Preset family | Required examples | Browser result preview |
| ------------------ | ---------------------------------------- | ------------------------------------------------------ |
| MP4 H.264/AAC | `mp4`, `libx264`, `aac` | usually, but verify actual output |
| WebM VP9/Opus | `webm`, `libvpx-vp9`, `libopus` | browser-dependent; Opus core regression gate applies |
| WebM VP8/Vorbis | `webm`, `libvpx`, `libvorbis` | commonly Chromium/Firefox |
| Matroska H.264/AAC | `matroska`, `libx264`, `aac` | generally download-only in browsers |
| animated WebP | `webp`, `libwebp_anim` | browser-dependent image preview |
| GIF | `gif`, `gif`, `palettegen`, `paletteuse` | broadly image-previewable |
| MP3 | `mp3`, `libmp3lame` | commonly playable |
| M4A/AAC | `ipod`, `aac` | commonly playable |
| Ogg Vorbis | `ogg`, `libvorbis` | browser-dependent |
| Opus | `opus`, `libopus` | browser-dependent; pinned-core regression gate applies |
| WAV/PCM | `wav`, `pcm_s16le` | commonly playable |
| FLAC | `flac`, `flac` | browser-dependent |
| Preset family | Required examples | Browser result preview |
| ------------------ | ---------------------------------------- | -------------------------------------------------------- |
| MP4 H.264/AAC | `mp4`, `libx264`, `aac` | usually, but verify actual output |
| WebM VP9/Opus | `webm`, `libvpx-vp9`, `libopus` | enabled when the loaded core advertises all requirements |
| WebM VP8/Vorbis | `webm`, `libvpx`, `libvorbis` | commonly Chromium/Firefox |
| Matroska H.264/AAC | `matroska`, `libx264`, `aac` | generally download-only in browsers |
| animated WebP | `webp`, `libwebp_anim` | browser-dependent image preview |
| GIF | `gif`, `gif`, `palettegen`, `paletteuse` | broadly image-previewable |
| MP3 | `mp3`, `libmp3lame` | commonly playable |
| M4A/AAC | `ipod`, `aac` | commonly playable |
| Ogg Vorbis | `ogg`, `libvorbis` | browser-dependent |
| Opus | `opus`, `libopus` | Chromium ST/MT encode and re-probe recorded |
| WAV/PCM | `wav`, `pcm_s16le` | commonly playable |
| FLAC | `flac`, `flac` | browser-dependent |
“Lossless” applies only to a lossless audio codec such as PCM/FLAC relative to
its decoded samples. It does not make a lossy source lossless. Stream-copy
@@ -77,11 +77,30 @@ remux avoids re-encoding compatible streams but may change container metadata.
- Normalized concat uses an explicit export preset and requires an explicit
insert-silence, drop-all-audio or reject policy when clips have mismatched
audio presence.
- Normalized concat can overlap every edit with one uniform 0.0410 second
`xfade` and, when audio is retained, `acrossfade`. End clips must contain at
least one transition duration and internal clips two; the active core must
expose each required filter.
- Crop, resize, frame-rate conversion, fades, normalization, burn-in and
contact sheets require specific filters discovered at runtime.
- Even-dimension correction is applied when the selected pixel format/encoder
requires it and is reported in the plan/result.
## Images and scene selection
Thumbnail/contact-sheet scene mode first performs a bounded full-source
analysis with `select`/`showinfo`, stopping after at most 100 qualifying
frames. Extraction then selects those exact source PTS values; no guessed time
rounding or remote analysis is used. If no frame meets the 0.010.95 threshold,
the operation reports that result and asks for a lower threshold or a
deterministic selection mode.
Contact-sheet labels require runtime `drawtext`. The app mounts only its
same-origin DejaVu Sans 2.37 asset after verifying 757,076 bytes and SHA-256
`7da195a74c55bef988d0d48f9508bd5d849425c1770dba5d7bfc6ce9ed848954`.
No remote or host-system font fallback is used. `SOURCE.md` and
`LICENSES/DEJAVU_FONTS.txt` provide provenance and terms.
## Subtitles
The text fixtures cover SRT, WebVTT and ASS import with explicit time shift.
@@ -115,8 +134,9 @@ elements do not reliably expose them, so ffprobe round-trip is authoritative.
- frame-accurate stream-copy trimming;
- complete metadata erasure/anonymity;
- browser preview of every FFmpeg-readable result;
- Opus presets until real non-empty ST/MT encoding smoke passes for core
0.12.10;
- Opus on browsers, inputs or deployments outside the exact reviewed
Chromium regression: both ST and MT pass the non-empty encode/re-probe gate,
but runtime capability discovery and normal per-job limits still apply;
- any capability omitted by the active core's runtime query.
Update this file only from re-probed generated/public-domain fixtures and

View File

@@ -1,6 +1,6 @@
# Known limitations
This is the conservative 0.1.0 development baseline. A capability appearing in
This is the conservative 0.2.0 release baseline. A capability appearing in
FFmpeg output does not remove these product/browser/resource limits.
## Functional
@@ -13,6 +13,9 @@ FFmpeg output does not remove these product/browser/resource limits.
frame-accurate. Accurate mode requires decoding/re-encoding.
- Stream-copy concatenate works only when selected streams and codec/container
parameters are compatible. Other input needs normalized re-encoding.
- Crossfades are uniform fade/triangular-curve transitions on normalized
sequential joins, not arbitrary transition effects or overlapping timeline
tracks. They require enough material on both sides of every internal edit.
- Re-encoding is not lossless. PCM/FLAC can preserve decoded audio samples but
cannot restore information already lost in a source.
- Metadata removal is best effort. Muxers may add structural/encoder fields,
@@ -26,6 +29,12 @@ FFmpeg output does not remove these product/browser/resource limits.
page discards queued work.
- A file-generating batch and its managed result collection are bounded to 255
outputs, leaving the 256th ZIP entry available for an optional export report.
- Scene analysis scans the source until it finds the requested changes or
reaches the end, retains at most 100 exact PTS results and can therefore take
about as long as a full decode. It does not begin an export implicitly when
no frame meets the chosen threshold.
- Labelled contact sheets require a core with `drawtext`; the reviewed local
font does not make that filter available on a core that omits it.
- Preview proxies are bounded, lossy H.264/AAC derivatives for local playback;
they do not replace the source or guarantee that every browser can play the
result.
@@ -38,8 +47,9 @@ FFmpeg output does not remove these product/browser/resource limits.
support fewer container/codec combinations.
- Browser support, codec policy and memory differ across Chromium, Firefox and
Safari and across desktop/mobile versions.
- Core 0.12.10 has an Opus regression risk. Opus remains release-gated until
non-empty, re-probeable ST and MT fixture outputs pass.
- The reviewed 0.12.10 core profile passes the non-empty Opus encode/re-probe
gate in isolated Chromium ST and MT runs. That evidence is not a
cross-browser or every-input Opus guarantee.
- MT needs HTTPS, COOP/COEP/CORP and `SharedArrayBuffer`. ST fallback works
without isolation but is not a guarantee that a large job fits.
- Top-level navigation is supported; iframe embedding is not.
@@ -69,7 +79,7 @@ FFmpeg output does not remove these product/browser/resource limits.
verification against the live container.
- The application is GPL-3.0-or-later and its native legal files and pinned
source identities are included in the release record. Publish the production
ZIP/checksum, exact `v0.1.0` source and FFmpeg Corresponding Source bundle
ZIP/checksum, exact `v0.2.0` source and FFmpeg Corresponding Source bundle
together; development-only smoke artifacts must not be distributed.
- Chromium covers a broad real pinned-core ST operation matrix, a real MT
H.264/AAC conversion, MT-to-ST fallback, nested static/Toolbox-context

View File

@@ -6,12 +6,13 @@ output at once. No hardware encoder is used.
## Fixed download footprint
Uncompressed self-hosted core assets for 0.12.10:
Uncompressed self-hosted core assets for
`0.12.10-reviewed-stack5m.1`:
| Mode | JavaScript/worker | WASM | Total |
| ------------- | ------------------: | -----------: | -----------: |
| single-thread | 111,804 B | 32,232,419 B | 32,344,223 B |
| multithread | 128,947 B + 2,115 B | 32,718,323 B | 32,849,385 B |
| single-thread | 111,804 B | 32,232,580 B | 32,344,384 B |
| multithread | 128,953 B + 2,115 B | 32,718,455 B | 32,849,523 B |
Only the selected mode is loaded. HTTP compression may reduce JavaScript
transfer but not necessarily WASM to the same degree; report transfer and
@@ -72,9 +73,18 @@ Estimated output warns at 512 MiB and is blocked at 1 GiB. FFmpeg jobs are
serial; the application retains at most eight scheduled operations in its
in-memory queue. Timeline clips are capped at 100, streams per input at 64,
images at 8192×8192/67,108,864 pixels, generated output files at 255,
contact-sheet cells at 500 and runtime at four hours. The documented
ffmpeg.wasm input ceiling is 2 GiB, but real limits can be substantially lower
on mobile or memory-constrained browsers.
contact-sheet cells at 500, scene-change results at 100, crossfades at 10
seconds and runtime at four hours. Scene selection is a bounded two-step
workflow but its analysis step can still decode the complete source when few
frames meet the threshold. The documented ffmpeg.wasm input ceiling is 2 GiB,
but real limits can be substantially lower on mobile or memory-constrained
browsers.
Source inspection has a bounded, size-aware watchdog: 30 seconds for small
files, a two-MiB-per-second scan budget for larger files, and a five-minute
ceiling. Recognized local audio/video can begin browser playback from its
temporary object URL while that worker inspection continues; completed probe
metadata remains authoritative for editing and export.
Lowering resolution, duration, frame rate, passes and output count reduces
work. MT can be faster but consumes more memory/CPU and requires isolation; ST

View File

@@ -18,7 +18,7 @@ X-Content-Type-Options: nosniff
Serve `.wasm` as `application/wasm`, JavaScript modules as a JavaScript MIME
type and JSON as `application/json`. Test real responses under
`/apps/av/vendor/ffmpeg/0.12.10/...`; a file-extension allowlist alone does not
`/apps/av/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/...`; a file-extension allowlist alone does not
prove the MIME type.
Suggested CSP:
@@ -43,45 +43,36 @@ form-action 'none';
`'unsafe-eval'` is unnecessary. `worker-src blob:` covers the wrapper-created
worker path. `media-src blob:` permits local source/result previews.
## Immutable reference and active-worktree state
## Reviewed Portal state
Portal revision `bda9da044d61c109afd9969d357cc27f76648938` already sends COOP
`same-origin`, COEP `require-corp`, CORP `same-origin`, `script-src 'self'
'wasm-unsafe-eval'`, and `worker-src 'self' blob:`. Its packaged nginx CSP does
**not** declare `media-src`; `default-src 'self'` therefore blocks local
`blob:` audio/video URLs. The expected browser diagnostic is equivalent to:
Portal revision `5c052bc6d1073a66600cfddc44c0e16da34bede8` (tag `v0.6.0`)
already sends COOP `same-origin`, COEP `require-corp`, CORP `same-origin`,
`script-src 'self' 'wasm-unsafe-eval'`, `worker-src 'self' blob:` and
`media-src 'self' blob:`. Its nginx profile also maps `.wasm` explicitly to
`application/wasm`. Local source and result Blob previews therefore require no
CSP exception beyond that reviewed narrow media directive.
```text
Refused to load media from 'blob:…' because it violates
"default-src 'self'".
```
As inspected on 2026-07-26, the active
`/mnt/DATA/git/toolbox-portal/deploy/nginx.conf` has an additional worktree
patch that extends the immutable FFmpeg cache rule from plain semantic versions
to the one exact reviewed build profile
`0.12.10-reviewed-stack5m.1`. The corresponding deployment tests accept the
five reviewed core files and `version.json` while rejecting mutable-looking
suffixes, malformed versions and unexpected paths. A clean temporary clone
containing that exact patch passed the AV release assembly smoke without a
known-header-gap override.
Smallest required Portal change: append exactly
`media-src 'self' blob:;` to that CSP. This permits only same-origin and
in-memory Blob media; it does not permit remote media hosts, inline script or
eval. If the Portal is not changed, conversion/download can remain available
but Blob source/result preview must show a clear disabled reason.
As inspected on 2026-07-24, the active
`/mnt/DATA/git/toolbox-portal/deploy/nginx.conf` contains that exact directive
as a local worktree patch. The worktree still resolves to the immutable
revision above, so the patch is useful for local deployment testing but is not
a committed Portal revision and must not be cited as published release
evidence. The clean-reference assembly smoke therefore continues to require
`--allow-known-header-gap` until a reviewed Portal commit contains the fix.
The nginx profile includes `.wasm` in its static allowlist/gzip types but
relies on the base image `mime.types`. Verify `Content-Type:
application/wasm` against the pinned image; add an explicit mapping if the
response differs.
Until the cache extension is committed, cite it only as staged integration
evidence, not as a published Portal revision. The clean `v0.6.0` rule leaves
the reviewed profile at `no-cache`; that affects performance, not loading,
MIME type, isolation or preview correctness.
## Caching
The immutable Portal reference's cache map makes Vite content-hashed assets
immutable but leaves versioned FFmpeg cores at `no-cache`. Correctness is
unaffected.
For performance, the exact directory
`apps/av/vendor/ffmpeg/0.12.10/{st,mt}/` may receive:
The staged Portal cache map makes Vite content-hashed assets, plain semantic
versions and the explicitly reviewed profile immutable. For performance, the
exact directory
`apps/av/vendor/ffmpeg/0.12.10-reviewed-stack5m.1/{st,mt}/` may receive:
```text
Cache-Control: public, max-age=31536000, immutable

View File

@@ -1,28 +1,31 @@
# Reference implementations
Inspection date: **2026-07-24**.
Inspection dates: **2026-07-24** (initial implementation) and
**2026-07-26** (remaining-slice integration).
The references were cloned beside av-tools under
`/mnt/DATA/git/references/`; no reference repository was nested in this
working tree. Revisions are full immutable commit ids.
| Repository | Revision inspected | Used for | Copied or adapted |
| -------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| av-tools, `git@git.add-ideas.de:zemion/av-tools.git` | no revision: canonical `main` was unborn and had no commits | canonical destination and licence/history check | the empty repository was scaffolded in place; no prior code existed |
| Toolbox SDK, `https://git.add-ideas.de/zemion/toolbox-sdk.git` | `53c40a61ba1581246f65773fcbb1c1cfd31ac98e` (SDK 0.2.2) | manifest schema/definition, `AppShell`, context behavior, shared styles, token-free registry, nested-path checks and toolchain baseline | published 0.2.2 packages are direct dependencies; documented usage patterns were followed; no SDK source file was copied |
| Toolbox Portal, `https://git.add-ideas.de/zemion/toolbox-portal.git` | `bda9da044d61c109afd9969d357cc27f76648938` | release ZIP/sidecar/lock formats, independent assembly, catalogue behavior, path security, nested deployment and production headers | no portal application source was copied; the documented artifact contract informed an independent release packager and smoke harness |
| ffmpeg.wasm, `https://github.com/ffmpegwasm/ffmpeg.wasm.git` | `f876f907c7e9b9bf51d4ed0b913a855a63ae63fc` | current API, worker lifecycle, filesystem, loading, ST/MT behavior, licence documentation and build layout | no reference-worktree code was copied; exact published npm packages are dependencies and their five core assets are copied verbatim by the vendor script |
| Repository | Revision inspected | Used for | Copied or adapted |
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| av-tools, `git@git.add-ideas.de:zemion/av-tools.git` | no revision: canonical `main` was unborn and had no commits | canonical destination and licence/history check | the empty repository was scaffolded in place; no prior code existed |
| Toolbox SDK, `https://git.add-ideas.de/zemion/toolbox-sdk.git` | `53c40a61ba1581246f65773fcbb1c1cfd31ac98e` (SDK 0.2.2) | manifest schema/definition, `AppShell`, context behavior, shared styles, token-free registry, nested-path checks and toolchain baseline | published 0.2.2 packages are direct dependencies; documented usage patterns were followed; no SDK source file was copied |
| Toolbox Portal, `https://git.add-ideas.de/zemion/toolbox-portal.git` | `bda9da044d61c109afd9969d357cc27f76648938` initially; `5c052bc6d1073a66600cfddc44c0e16da34bede8` for final integration | release ZIP/sidecar/lock formats, independent assembly, catalogue behavior, path security, nested deployment and production headers | no portal application source was copied; the AV smoke harness consumes only an exact cloned Portal revision; the separate Portal worktree contains its own reviewed integration patch |
| ffmpeg.wasm, `https://github.com/ffmpegwasm/ffmpeg.wasm.git` | `f876f907c7e9b9bf51d4ed0b913a855a63ae63fc`; pinned release baseline `71aa99d37c02a7b4c435275ca9ef50e612f6efa1` | current API, worker lifecycle, filesystem, loading, ST/MT behavior, licence documentation and build layout | no reference-worktree source was copied; wrapper/util remain exact npm dependencies, while the five core assets are rebuilt from the recorded source/toolchain/patch profile and verified against the build lock |
For the **pinned** package set, the more specific upstream release tag
`v12.15` at `71aa99d37c02a7b4c435275ca9ef50e612f6efa1` was also inspected. It
contains `@ffmpeg/ffmpeg` 0.12.15 and core/core-mt 0.12.10. That revision's
build selects FFmpeg n5.1.4.
contains `@ffmpeg/ffmpeg` 0.12.15 and the source configuration for core
0.12.10. That revision's build selects FFmpeg n5.1.4. The shipped
`0.12.10-reviewed-stack5m.1` assets additionally apply upstream ffmpeg.wasm
commit `b409e36475bc21f0451b5b1e1d126fa82871439a`; exact build and source
identities are in `SOURCE.md` and `docs/FFMPEG_BUILD.md`.
The user's active `/mnt/DATA/git/toolbox-portal` worktree still has Portal
revision `bda9da044d61c109afd9969d357cc27f76648938` as `HEAD`, but currently
contains a local `media-src 'self' blob:` nginx CSP patch. That mutable
worktree state is documented for deployment testing only; it does not replace
the immutable reference in the table.
The active `/mnt/DATA/git/toolbox-portal` worktree has immutable revision
`5c052bc6d1073a66600cfddc44c0e16da34bede8` as `HEAD`. Its staged cache-rule
extension is documented separately and is not represented as a published
revision.
Official behavior references:

View File

@@ -11,10 +11,10 @@ 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.1.0` at that exact commit;
2. create and verify annotated tag `v0.2.0` 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 core packages and linked libraries;
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
@@ -44,6 +44,7 @@ Normal packaging validates the root GPL version 3 text and matching
```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
@@ -56,19 +57,19 @@ 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.1.0.zip
release/av-tools-0.1.0.zip.sha256
release/ffmpeg-core-0.12.10-corresponding-source.tar.xz
release/ffmpeg-core-0.12.10-corresponding-source.tar.xz.sha256
release/av-tools-0.2.0.zip
release/av-tools-0.2.0.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-corresponding-source.tar.xz.sha256)
unzip -l release/av-tools-0.1.0.zip
tar -tJf release/ffmpeg-core-0.12.10-corresponding-source.tar.xz
(cd release && sha256sum -c ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz.sha256)
unzip -l release/av-tools-0.2.0.zip
tar -tJf release/ffmpeg-core-0.12.10-reviewed-stack5m.1-corresponding-source.tar.xz
```
The packager:
@@ -90,13 +91,13 @@ When used against a fixture without an application licence, the escape hatch add
## 4. Portal assembly smoke
Use the clean reference clone beside av-tools, never the user's active Portal
worktree:
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.1.0.zip \
--allow-known-header-gap
--artifact release/av-tools-0.2.0.zip \
--portal-root ../toolbox-portal
```
The smoke harness clones the exact Portal HEAD to a temporary directory,
@@ -106,19 +107,23 @@ 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.
Without `--allow-known-header-gap`, the clean immutable Portal reference's CSP
omission of `media-src blob:` is a failing deployment check. The override still
reports the gap and is only for testing archive assembly. See
`docs/PORTAL_REQUIREMENTS.md`.
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.
The user's active `/mnt/DATA/git/toolbox-portal` worktree contains the narrow
directive as a local patch, but the smoke intentionally does not consume that
mutable worktree. Until the patch exists in a reviewed immutable Portal
revision, retain the clean-reference failure/override behavior above.
`--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.1.0` checkout, rerun all checks, create the ZIP once, verify
From a clean `v0.2.0` 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

View File

@@ -39,9 +39,10 @@ exportable diagnostics.
Metadata is rendered as React text, never `dangerouslySetInnerHTML`. Subtitle
text is parsed and rendered or sent through a generated local file; it is not
inserted as HTML. Extracted URLs are inert text. The application does not open
links from media automatically. No remote font is fetched; ASS burn-in uses
packaged/system-generic font configuration only when the required local
capability is available.
links from media automatically. No remote font is fetched. Contact-sheet labels
mount only the same-origin, size/SHA-256-verified DejaVu asset and fail closed
without `drawtext`; ASS burn-in uses packaged/system-generic font configuration
only when the required local capability is available.
Preview/download URLs are `blob:` values made from local bytes. They are
revoked on replacement, project close and unmount. Browser support for a