Audit immutable input isolation for existing image/video decoders #501

Open
opened 2026-09-30 08:37:31 +00:00 by kayg · 10 comments
Owner

Static follow-up from #410 document sandbox review.

The new document worker uses a bounded, kernel-sealed PDF snapshot and never passes its original Home inode to an untrusted document loader. The pre-existing image/video paths still pass held source descriptors to native tools. Audit those paths against the same immutable-input requirement, including probes and playback/transcode workers, and reuse calternal_fs::sealed_media_input or an equivalent kernel-enforced boundary with an appropriate resource budget.

This is a defense-in-depth finding from source review; no native decoder compromise or data corruption was reproduced. Do not treat a descriptor opened read-only as proof that the underlying service-owned inode cannot be changed by a compromised decoder. No exploit payloads are attached.

The #410 job fixes and tests the newly introduced document-thumbnail mode. A broader image/video change needs its own memory/performance and real-decoder validation.

Static follow-up from #410 document sandbox review. The new document worker uses a bounded, kernel-sealed PDF snapshot and never passes its original Home inode to an untrusted document loader. The pre-existing image/video paths still pass held source descriptors to native tools. Audit those paths against the same immutable-input requirement, including probes and playback/transcode workers, and reuse `calternal_fs::sealed_media_input` or an equivalent kernel-enforced boundary with an appropriate resource budget. This is a defense-in-depth finding from source review; no native decoder compromise or data corruption was reproduced. Do not treat a descriptor opened read-only as proof that the underlying service-owned inode cannot be changed by a compromised decoder. No exploit payloads are attached. The #410 job fixes and tests the newly introduced document-thumbnail mode. A broader image/video change needs its own memory/performance and real-decoder validation.
Author
Owner

Starting #501 on branch job/fix-501.

Initial HEAD/base SHA: 558457cf32e1d429da3834a05ff2720d11284302 (branch is based on origin/dev; it is 277 commits behind the current remote ref).

I am tracing the image/video decode, probe, and playback/transcode paths and the #410 sealed document-input implementation before changing code.

Starting #501 on branch `job/fix-501`. Initial HEAD/base SHA: `558457cf32e1d429da3834a05ff2720d11284302` (branch is based on `origin/dev`; it is 277 commits behind the current remote ref). I am tracing the image/video decode, probe, and playback/transcode paths and the #410 sealed document-input implementation before changing code.
Author
Owner

Defensive audit finding: the Files worker passes its original held Home file descriptor to vipsheader/vips for image dimension probes and thumbnails, to ffprobe/ffmpeg for video probes and thumbnails, and it makes only the PDF branch with calternal_fs::sealed_media_input. The Video Job also calls video_header_is_allowed(&source.file, ...) and later passes source.file to FFmpeg. The probe and transcode are separate consumers of the same mutable inode. This matches the source-review concern in #501; no decoder compromise or data corruption was reproduced.

The #410 launcher currently enforces seals and a 64 MiB cap only for document-thumbnail. The image, video-thumbnail, probe and video modes accept stdin without that boundary. I am extending the same kernel-sealed snapshot invariant to those native input modes, keeping existing image/video byte caps and the shared media semaphore as the copy budget. I am adding launcher rejection tests plus real image/video decoder validation.

Defensive audit finding: the Files worker passes its original held Home file descriptor to `vipsheader`/`vips` for image dimension probes and thumbnails, to `ffprobe`/`ffmpeg` for video probes and thumbnails, and it makes only the PDF branch with `calternal_fs::sealed_media_input`. The Video Job also calls `video_header_is_allowed(&source.file, ...)` and later passes `source.file` to FFmpeg. The probe and transcode are separate consumers of the same mutable inode. This matches the source-review concern in #501; no decoder compromise or data corruption was reproduced. The #410 launcher currently enforces seals and a 64 MiB cap only for `document-thumbnail`. The image, video-thumbnail, probe and video modes accept stdin without that boundary. I am extending the same kernel-sealed snapshot invariant to those native input modes, keeping existing image/video byte caps and the shared media semaphore as the copy budget. I am adding launcher rejection tests plus real image/video decoder validation.
Author
Owner

Defensive media isolation audit complete

Branch: job/fix-501
Head: f9384a4f5b08485a90ac00bf84acfb9ff5793084
Commits: dfc5d532d (calternal-fs snapshot helper), 6ef98659b (Files thumbnail sandbox), a853ddc58 (Video HLS sandbox), followed by the requested merge of current origin/dev.

Finding and fix

Before the change, Files image probes/thumbnails and Video FFprobe/FFmpeg jobs passed the original held Home file descriptor. The launcher enforced sealed input only for document thumbnails. A read-only Home descriptor therefore reached native image/video tools without the #410 immutable-input boundary.

The workers now copy each accepted image or video once to a bounded, fully sealed memfd through calternal-fs. The image limit is 512 MiB; the video limit is 1 GiB. A thumbnail job reuses its snapshot for probing and both sizes. A Video job reuses its snapshot for FFprobe and FFmpeg. Both acquire the existing two-slot media limit before the copy. The launcher checks all four seals, regular-file type, and the mode-specific size before bubblewrap setup. The document mode retains its 64 MiB limit.

Regression and before/after evidence

tests/adversarial/test-media-sandbox.sh rejects unsealed, partly sealed, and sparse over-limit descriptors before namespace setup in every native media mode. It then checks descriptor isolation in the real namespace and runs real vips, FFprobe, FFmpeg thumbnail, and HLS paths. Final output:

PASS: bounded sealed image/video probes, thumbnails and HLS transcode

The #410 compatibility check also passed:

PASS: document namespace, private input, inherited limits and network policy

Before: zero snapshot-copy bytes; native image/video tools received the held Home descriptor. After: local profile of a 64 MiB source, 10 sequential runs and a two-job burst:

{"schema":"calternal.perf.media-snapshot/1","input_bytes":67108864,"sequential_runs":10,"sequential_p50_ms":71.704,"sequential_p95_ms":115.006,"burst_size":2,"burst_p95_ms":110.059,"burst_wall_ms":119.737,"cpu_ms":401.517,"peak_rss_bytes":99418112,"peak_snapshot_bytes":134217728}

This is a local measurement. The repository baseline has no prior snapshot-helper latency sample.

Final gates

cargo fmt --check exited 0 with no output.

Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 07s
Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 27s
Finished `dev` profile [unoptimized + debuginfo] target(s) in 56.06s
test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 15.78s
test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.60s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 146 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 243.38s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.66s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

The three clippy lines are in order for calternal-fs, calternal-plugin-files, and calternal-plugin-video, each run with --all-targets -- -D warnings. The test results are in the same crate order.

Decisions and gaps

I reused the existing 512 MiB image and 1 GiB video source limits and counted snapshot allocation inside the existing two-slot media limit. DESIGN §39 now records that boundary. The separate in-process background-image validator uses Rust image outside this native media sandbox; it remains bounded by a 20 MiB input limit and 256 MiB decode allocation limit, but was not moved by this sandbox-focused issue. Direct video byte streaming to the browser does not invoke a server decoder.

## Defensive media isolation audit complete **Branch:** `job/fix-501` **Head:** `f9384a4f5b08485a90ac00bf84acfb9ff5793084` **Commits:** `dfc5d532d` (`calternal-fs` snapshot helper), `6ef98659b` (Files thumbnail sandbox), `a853ddc58` (Video HLS sandbox), followed by the requested merge of current `origin/dev`. ### Finding and fix Before the change, Files image probes/thumbnails and Video FFprobe/FFmpeg jobs passed the original held Home file descriptor. The launcher enforced sealed input only for document thumbnails. A read-only Home descriptor therefore reached native image/video tools without the #410 immutable-input boundary. The workers now copy each accepted image or video once to a bounded, fully sealed memfd through `calternal-fs`. The image limit is 512 MiB; the video limit is 1 GiB. A thumbnail job reuses its snapshot for probing and both sizes. A Video job reuses its snapshot for FFprobe and FFmpeg. Both acquire the existing two-slot media limit before the copy. The launcher checks all four seals, regular-file type, and the mode-specific size before bubblewrap setup. The document mode retains its 64 MiB limit. ### Regression and before/after evidence `tests/adversarial/test-media-sandbox.sh` rejects unsealed, partly sealed, and sparse over-limit descriptors before namespace setup in every native media mode. It then checks descriptor isolation in the real namespace and runs real vips, FFprobe, FFmpeg thumbnail, and HLS paths. Final output: ```text PASS: bounded sealed image/video probes, thumbnails and HLS transcode ``` The #410 compatibility check also passed: ```text PASS: document namespace, private input, inherited limits and network policy ``` Before: zero snapshot-copy bytes; native image/video tools received the held Home descriptor. After: local profile of a 64 MiB source, 10 sequential runs and a two-job burst: ```text {"schema":"calternal.perf.media-snapshot/1","input_bytes":67108864,"sequential_runs":10,"sequential_p50_ms":71.704,"sequential_p95_ms":115.006,"burst_size":2,"burst_p95_ms":110.059,"burst_wall_ms":119.737,"cpu_ms":401.517,"peak_rss_bytes":99418112,"peak_snapshot_bytes":134217728} ``` This is a local measurement. The repository baseline has no prior snapshot-helper latency sample. ### Final gates `cargo fmt --check` exited 0 with no output. ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 07s Finished `dev` profile [unoptimized + debuginfo] target(s) in 6m 27s Finished `dev` profile [unoptimized + debuginfo] target(s) in 56.06s test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 15.78s test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.60s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 146 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 243.38s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.66s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` The three clippy lines are in order for `calternal-fs`, `calternal-plugin-files`, and `calternal-plugin-video`, each run with `--all-targets -- -D warnings`. The test results are in the same crate order. ### Decisions and gaps I reused the existing 512 MiB image and 1 GiB video source limits and counted snapshot allocation inside the existing two-slot media limit. DESIGN §39 now records that boundary. The separate in-process background-image validator uses Rust `image` outside this native media sandbox; it remains bounded by a 20 MiB input limit and 256 MiB decode allocation limit, but was not moved by this sandbox-focused issue. Direct video byte streaming to the browser does not invoke a server decoder.
Author
Owner

Current head addendum

Current head is d38a7f8b1 (full SHA: d38a7f8b18f1061f43bb71f8a87379133ac52f4d). This adds comment and DESIGN clarification only; bash -n deploy/media-sandbox and git diff --check pass. The Rust gate results in the preceding report remain applicable.

Scope decision: #501 closes the immutable-input boundary requested in the issue. The image and video modes retain their existing namespaces, capability drops, and resource limits. The seccomp filters remain document-thumbnail-only; I did not broaden those filters as part of this immutable-input change.

## Current head addendum Current head is `d38a7f8b1` (full SHA: `d38a7f8b18f1061f43bb71f8a87379133ac52f4d`). This adds comment and DESIGN clarification only; `bash -n deploy/media-sandbox` and `git diff --check` pass. The Rust gate results in the preceding report remain applicable. Scope decision: #501 closes the immutable-input boundary requested in the issue. The image and video modes retain their existing namespaces, capability drops, and resource limits. The seccomp filters remain document-thumbnail-only; I did not broaden those filters as part of this immutable-input change.
Author
Owner

Round 2 start: branch job/fix-501, base cc25c441b7. I am implementing the approved size-tiered immutable media snapshot path, preserving the existing byte caps and two-slot limit. I will add an on-disk sandbox regression and measure the requested video sizes if the locked perf VM is available.

Round 2 start: branch job/fix-501, base cc25c441b7a974185622a1dee853cf38686d2b67. I am implementing the approved size-tiered immutable media snapshot path, preserving the existing byte caps and two-slot limit. I will add an on-disk sandbox regression and measure the requested video sizes if the locked perf VM is available.
Author
Owner

Finding: Root::open_split keeps instance_data and user_data on separate held roots, so .system is not guaranteed to share a filesystem with Homes. The large snapshot scratch directory is therefore .user-data-internal/media-snapshots under the user-data root, and snapshot creation checks the opened source and scratch directory device IDs before reflink or copy.

Finding: `Root::open_split` keeps `instance_data` and `user_data` on separate held roots, so `.system` is not guaranteed to share a filesystem with Homes. The large snapshot scratch directory is therefore `.user-data-internal/media-snapshots` under the user-data root, and snapshot creation checks the opened source and scratch directory device IDs before reflink or copy.
Author
Owner

Finding: the first sandbox run rejected the new disk-tier video test after launcher input validation because the test omitted the inherited HLS output directory descriptor. bwrap reported Can\047t find source path /proc/self/fd/1. The test now supplies the same output descriptor used by the existing memfd HLS case; I am rerunning the bounded media sandbox round.

Finding: the first sandbox run rejected the new disk-tier video test after launcher input validation because the test omitted the inherited HLS output directory descriptor. `bwrap` reported `Can\047t find source path /proc/self/fd/1`. The test now supplies the same output descriptor used by the existing memfd HLS case; I am rerunning the bounded media sandbox round.
Author
Owner

Finding: the shared document sandbox test produced pdf.webp but left text.webp empty. Its stderr showed the launcher rejected the text-card input descriptor. The Files worker sends a bounded server-generated escaped SVG stream for the fixed calternal-text-thumbnail action; it does not pass a Home inode. I am narrowing the immutable-descriptor check to PDF actions, while the fixed text action stays inside the existing restricted namespace.

Finding: the shared document sandbox test produced `pdf.webp` but left `text.webp` empty. Its stderr showed the launcher rejected the text-card input descriptor. The Files worker sends a bounded server-generated escaped SVG stream for the fixed `calternal-text-thumbnail` action; it does not pass a Home inode. I am narrowing the immutable-descriptor check to PDF actions, while the fixed text action stays inside the existing restricted namespace.
Author
Owner

Finding: the shared launcher applied the media-snapshot descriptor check to the server-generated text-card SVG stream. In the document sandbox compatibility probe, PDF output was valid but text.webp was empty; the launcher rejected the stream before vips read it.

Fix: enforce the snapshot descriptor policy for PDF actions only. Text cards use the existing bounded, escaped server-generated SVG stream and do not read a Home inode. Updated DESIGN §39 and launcher comments. Commit: dbe454b3f.

Evidence: tests/adversarial/test-document-sandbox.sh exited 0. Output included PASS: document namespace, private input, inherited limits and network policy, PASS: PDF link/script metadata and bounded SVG references/entities stay isolated, and PASS: explicit PDF and SVG loaders produce WebP; PDF action rejects JPEG.

Finding: the shared launcher applied the media-snapshot descriptor check to the server-generated text-card SVG stream. In the document sandbox compatibility probe, PDF output was valid but `text.webp` was empty; the launcher rejected the stream before vips read it. Fix: enforce the snapshot descriptor policy for PDF actions only. Text cards use the existing bounded, escaped server-generated SVG stream and do not read a Home inode. Updated DESIGN §39 and launcher comments. Commit: `dbe454b3f`. Evidence: `tests/adversarial/test-document-sandbox.sh` exited 0. Output included `PASS: document namespace, private input, inherited limits and network policy`, `PASS: PDF link/script metadata and bounded SVG references/entities stay isolated`, and `PASS: explicit PDF and SVG loaders produce WebP; PDF action rejects JPEG`.
Author
Owner

Round 2 complete. Head: 198ddee66c28f578184859b3e11be408675d7aef.

Built

  • Added size-tiered immutable decoder snapshots in calternal-fs: up to and including 64 MiB uses a sealed memfd; larger inputs use an anonymous file on the Home filesystem, with FICLONE when supported and a streamed copy otherwise. The fallback for filesystems without O_TMPFILE unlinks an exclusive 0600 file before writing. The decoder receives a read-only descriptor with no reachable path.
  • Kept the two-slot maximum and reserved one lane for small work. Snapshot creation happens while a permit is held. Large snapshots/transcodes use only the shared lane, so they leave a lane for small thumbnails.
  • Enforced snapshot descriptors at the native sandbox boundary and retained the hostile descriptor checks. Added an on-disk descriptor probe that checks writes fail and the deleted path cannot be reopened.
  • Kept text-card SVG on its bounded server-generated escaped stream. The document sandbox requires a snapshot only for Home-backed PDF actions. Fixed a regression where the snapshot check rejected the text-card stream and produced an empty WebP.
  • Added bench/media-snapshot.sh and docs/perf/runs/2026-10-01-501-media-snapshots.md.

Performance

The perf VM lock was held by another job. Per the shared-host rule, I did not wait or measure there without the lock. The local profile measured the snapshot helper process on a busy host using sparse files with size-correct but invalid video contents. It does not measure a running server, FFmpeg, or server peak RSS. The profile labels and caveats are in docs/perf/runs/2026-10-01-501-media-snapshots.md.

Size Path p50 p95 Burst wall CPU Process peak RSS Disk read Disk write Memfd bytes in burst
64 MiB Before, memfd 100.850 ms 165.129 ms 148.957 ms (2) 223.819 ms 3,219,456 B 0 B 0 B 134,217,728 B
64 MiB After, tiered 77.397 ms 79.761 ms 117.088 ms (2) 190.501 ms 3,350,528 B 0 B 0 B 134,217,728 B
512 MiB Before, memfd 689.230 ms 829.951 ms 811.922 ms (1) 1,182.085 ms 3,223,552 B 0 B 0 B 536,870,912 B
512 MiB After, tiered 1,133.543 ms 1,479.358 ms 1,373.160 ms (1) 2,269.651 ms 3,276,800 B 8,192 B 2,147,483,648 B 0 B
1 GiB Before, memfd 1,240.587 ms 2,277.296 ms 862.393 ms (1) 2,706.405 ms 3,272,704 B 0 B 0 B 1,073,741,824 B
1 GiB After, tiered 2,637.246 ms 3,360.466 ms 2,550.267 ms (1) 3,434.250 ms 3,141,632 B 0 B 3,221,225,472 B 0 B

The local ext4 scratch directory did not support reflinks, so the disk tier used streamed copies. Memfd page backing does not appear in process RSS; the old single-input 1 GiB path held 1 GiB of memfd pages, while the tiered path held zero memfd pages above 64 MiB. Disk writes were measured by the helper process. A server-level RSS and perf VM run remain gaps.

Gates

cargo fmt --all --check exited 0 with no output.

Clippy output:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.69s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 41.65s
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.47s

cargo test result lines, verbatim:

test result: ok. 54 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 13.39s
test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 11.69s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 148 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 108.34s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Adversarial probes passed:

PASS: bounded sealed image/video probes, thumbnails and HLS transcode
PASS: document namespace, private input, inherited limits and network policy
PASS: PDF link/script metadata and bounded SVG references/entities stay isolated
PASS: explicit PDF and SVG loaders produce WebP; PDF action rejects JPEG

Decisions

  • Use the shared media slot as the large-work lane and reserve the other one for small thumbnail work. Small work can use either lane; large work cannot consume the reserved lane.
  • Keep the document text-card path as server-generated escaped SVG streamed through fd 0. It does not refer to a Home inode, so the Home snapshot descriptor check applies to the PDF actions only.

cargo clean removed 10,102 files (4.2 GiB). No web build output was present. No migrations changed.

Round 2 complete. Head: `198ddee66c28f578184859b3e11be408675d7aef`. ## Built - Added size-tiered immutable decoder snapshots in `calternal-fs`: up to and including 64 MiB uses a sealed memfd; larger inputs use an anonymous file on the Home filesystem, with `FICLONE` when supported and a streamed copy otherwise. The fallback for filesystems without `O_TMPFILE` unlinks an exclusive 0600 file before writing. The decoder receives a read-only descriptor with no reachable path. - Kept the two-slot maximum and reserved one lane for small work. Snapshot creation happens while a permit is held. Large snapshots/transcodes use only the shared lane, so they leave a lane for small thumbnails. - Enforced snapshot descriptors at the native sandbox boundary and retained the hostile descriptor checks. Added an on-disk descriptor probe that checks writes fail and the deleted path cannot be reopened. - Kept text-card SVG on its bounded server-generated escaped stream. The document sandbox requires a snapshot only for Home-backed PDF actions. Fixed a regression where the snapshot check rejected the text-card stream and produced an empty WebP. - Added `bench/media-snapshot.sh` and `docs/perf/runs/2026-10-01-501-media-snapshots.md`. ## Performance The perf VM lock was held by another job. Per the shared-host rule, I did not wait or measure there without the lock. The local profile measured the snapshot helper process on a busy host using sparse files with size-correct but invalid video contents. It does not measure a running server, FFmpeg, or server peak RSS. The profile labels and caveats are in `docs/perf/runs/2026-10-01-501-media-snapshots.md`. | Size | Path | p50 | p95 | Burst wall | CPU | Process peak RSS | Disk read | Disk write | Memfd bytes in burst | |---|---|---:|---:|---:|---:|---:|---:|---:|---:| | 64 MiB | Before, memfd | 100.850 ms | 165.129 ms | 148.957 ms (2) | 223.819 ms | 3,219,456 B | 0 B | 0 B | 134,217,728 B | | 64 MiB | After, tiered | 77.397 ms | 79.761 ms | 117.088 ms (2) | 190.501 ms | 3,350,528 B | 0 B | 0 B | 134,217,728 B | | 512 MiB | Before, memfd | 689.230 ms | 829.951 ms | 811.922 ms (1) | 1,182.085 ms | 3,223,552 B | 0 B | 0 B | 536,870,912 B | | 512 MiB | After, tiered | 1,133.543 ms | 1,479.358 ms | 1,373.160 ms (1) | 2,269.651 ms | 3,276,800 B | 8,192 B | 2,147,483,648 B | 0 B | | 1 GiB | Before, memfd | 1,240.587 ms | 2,277.296 ms | 862.393 ms (1) | 2,706.405 ms | 3,272,704 B | 0 B | 0 B | 1,073,741,824 B | | 1 GiB | After, tiered | 2,637.246 ms | 3,360.466 ms | 2,550.267 ms (1) | 3,434.250 ms | 3,141,632 B | 0 B | 3,221,225,472 B | 0 B | The local ext4 scratch directory did not support reflinks, so the disk tier used streamed copies. Memfd page backing does not appear in process RSS; the old single-input 1 GiB path held 1 GiB of memfd pages, while the tiered path held zero memfd pages above 64 MiB. Disk writes were measured by the helper process. A server-level RSS and perf VM run remain gaps. ## Gates `cargo fmt --all --check` exited 0 with no output. Clippy output: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.69s Finished `dev` profile [unoptimized + debuginfo] target(s) in 41.65s Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.47s ``` `cargo test` result lines, verbatim: ```text test result: ok. 54 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 13.39s test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 11.69s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 148 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 108.34s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` Adversarial probes passed: ```text PASS: bounded sealed image/video probes, thumbnails and HLS transcode PASS: document namespace, private input, inherited limits and network policy PASS: PDF link/script metadata and bounded SVG references/entities stay isolated PASS: explicit PDF and SVG loaders produce WebP; PDF action rejects JPEG ``` ## Decisions - Use the shared media slot as the large-work lane and reserve the other one for small thumbnail work. Small work can use either lane; large work cannot consume the reserved lane. - Keep the document text-card path as server-generated escaped SVG streamed through fd 0. It does not refer to a Home inode, so the Home snapshot descriptor check applies to the PDF actions only. `cargo clean` removed 10,102 files (4.2 GiB). No web build output was present. No migrations changed.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#501
No description provided.