feat: publish av-tools 0.1.0
This commit is contained in:
115
docs/PORTAL_REQUIREMENTS.md
Normal file
115
docs/PORTAL_REQUIREMENTS.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Toolbox Portal requirements
|
||||
|
||||
av-tools is built and packaged independently. Toolbox Portal consumes the
|
||||
exact ZIP and SHA-256 from a reviewed release lock; it must never import the
|
||||
app source into its React build.
|
||||
|
||||
## Required serving behavior
|
||||
|
||||
All app, wrapper, core, WASM and worker responses are same-origin and served
|
||||
over HTTPS (or trusted localhost). Apply:
|
||||
|
||||
```text
|
||||
Cross-Origin-Opener-Policy: same-origin
|
||||
Cross-Origin-Embedder-Policy: require-corp
|
||||
Cross-Origin-Resource-Policy: same-origin
|
||||
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
|
||||
prove the MIME type.
|
||||
|
||||
Suggested CSP:
|
||||
|
||||
```text
|
||||
default-src 'self';
|
||||
script-src 'self' 'wasm-unsafe-eval';
|
||||
worker-src 'self' blob:;
|
||||
connect-src 'self';
|
||||
img-src 'self' blob: data:;
|
||||
media-src 'self' blob:;
|
||||
font-src 'self';
|
||||
style-src 'self';
|
||||
object-src 'none';
|
||||
frame-src 'none';
|
||||
frame-ancestors 'none';
|
||||
base-uri 'none';
|
||||
form-action 'none';
|
||||
```
|
||||
|
||||
`'wasm-unsafe-eval'` is the narrow WebAssembly permission; broad
|
||||
`'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
|
||||
|
||||
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:
|
||||
|
||||
```text
|
||||
Refused to load media from 'blob:…' because it violates
|
||||
"default-src 'self'".
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
## 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:
|
||||
|
||||
```text
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
```
|
||||
|
||||
Only do this while a version path is immutable and verified against
|
||||
`version.json`. Keep `index.html`, manifest/catalog/release JSON and legal
|
||||
notices revalidated.
|
||||
|
||||
## Nested path and context
|
||||
|
||||
The artifact uses `base: './'`, `entry: './'`, a relative icon, a relative
|
||||
manifest URL and relative core URLs. Portal may therefore target `av`, yielding
|
||||
`apps/av/`. Do not rewrite files to root-absolute `/assets` or `/vendor`.
|
||||
Use top-level navigation; embedding is unsupported.
|
||||
|
||||
The app remains usable without valid Toolbox context. It validates context
|
||||
version/origin and falls back to standalone shell behavior without moving or
|
||||
duplicating suite controls.
|
||||
|
||||
## Fallback contract
|
||||
|
||||
MT requires all isolation headers plus secure context and
|
||||
`SharedArrayBuffer`. When any prerequisite or MT load fails, the app terminates
|
||||
that instance and loads ST. The manifest intentionally declares
|
||||
`crossOriginIsolated: false` because isolation is not an unconditional
|
||||
requirement; it declares workers, secure context, IndexedDB and top-level
|
||||
context.
|
||||
|
||||
See `scripts/portal-assembly-smoke.mjs` and `docs/RELEASE.md` for the temporary,
|
||||
non-mutating assembly procedure.
|
||||
Reference in New Issue
Block a user