Plan: attachment previews (#865) #871
Open
kayg
wants to merge 1 commit from
plan/previews-865 into dev
pull from: plan/previews-865
merge into: kayg:dev
kayg:main
kayg:feat/contrast
kayg:feat/style-sheet-fixes
kayg:storage/wal-checkpoint-off-save-1051
kayg:t3/paged-search-reconcile-final
kayg:feat/pass8
kayg:review/calendar-2
kayg:fix/shared-row-swipes
kayg:dev
kayg:feat/collections-db
kayg:fix/instant-keys-1056
kayg:feat/money-round
kayg:perf/stalls-1054
kayg:wip/tiering-v3-cold4
kayg:wip/tiering-v3-cold5
kayg:port/rows-actions
kayg:port/rows-drop
kayg:port/hidden-blocks
kayg:port/rows
kayg:port/port-tables
kayg:port/port-tables-2
kayg:t3/mail-1011-liveness
kayg:port/devices
kayg:port/port-attachments
kayg:port/port-attachments-2
kayg:port/port-attachments-3
kayg:docs/design-consistency
kayg:docs/engineering-standards
kayg:fix/rusqlite-0.41-rustsec-2026-0459
kayg:feat/iphone-fixes
kayg:shared/restore-and-stale-918-919
kayg:fix/phone-top-band-contrast
kayg:feat/notes-approve
kayg:perf/soak-max-gate
kayg:feat/files-s1-identity
kayg:fix/lifecycle-event-id
kayg:feat/quickfix
kayg:wip/tiering-v3-cold
kayg:perf/web-mockup-frame-fixes
kayg:port/contacts-merge
kayg:port/contacts-edit
kayg:test/shared-room-no-deleted-text
kayg:perf/first-paint-credits
kayg:fix/shared-history-after-grant
kayg:fix/phone-swipe-regressions
kayg:feat/contrast-r1
kayg:review/sharing-pr3-review
kayg:feat/tiering-v3-s2-tags
kayg:feat/folder-drop
kayg:fix/deskpills-lazy-share
kayg:feat/sharing-s1-pr3
kayg:tmp/money-round-before
kayg:fix/phone-pane-backdrop-roots
kayg:fix/palette-preload-chips
kayg:fix/invite-defaults
kayg:port/tasks-matrix
kayg:fix/restore-green-gates
kayg:fix/sharing-fast-path-hardening
kayg:t3/photos-s1
kayg:feat/tiering-v3-s1-namespace
kayg:notes-archive-hide
kayg:feat/tasks-actions
kayg:t3/photos-plan-slice-one
kayg:feat/whiteboard-s1
kayg:t3/paged-search-reconcile
kayg:t3/smooth-pane-transitions
kayg:t3/index-position-startup-scan
kayg:fix/private-staging-759b-r2
kayg:feat/dav-transport
kayg:feat/imap-notes-fetch
kayg:feat/imap-notes-projection
kayg:feat/imap-notes-readonly
kayg:feat/imap-notes-auth
kayg:feat/imap-notes-server-foundation
kayg:docs/undo-block-ids-plan
kayg:fix/undo-768
kayg:proto/block-identity-v7d
kayg:issue/carddav-read-perf-fix-r2
kayg:issue/carddav-read-r2
kayg:docs/imap-766-plan-v2
kayg:docs/imap-notes-plan
kayg:docs/quota-plan-2
kayg:fix/parallel-test-flakes
kayg:feat/contacts-companion-pure
kayg:docs/calendar-backend-v2-plan
kayg:feat/calendar-ical-converter
kayg:docs/tasks-writes-v2-plan
kayg:docs/carddav-writes-v2-plan
kayg:docs/contacts-import-v2-plan
kayg:issue/610-pm-midnight
kayg:feat/calendar-v2-s1-containment
kayg:docs/dav-recorder-v2-plan
kayg:plan/save-log-durable-entry
kayg:fix/e2e-data-on-ram
kayg:feat/appwindow3
kayg:feat/appwindow2
kayg:feat/appwindow
kayg:feat/money-p1
kayg:feat/keys-sheet
kayg:review/calendar-2-themes
kayg:feat/smooth-cursor
kayg:fix/float-style
kayg:review/calendar-2-float
kayg:release/2026-11-06-hotfix
kayg:archive/port/rows-drop-code
kayg:archive/port/rows-actions
kayg:archive/port/rows
kayg:scratch/tasks-894-ui-gates
kayg:review/calendar-2-night-wip
kayg:release/2026-11-05
kayg:archive/feat/tiering-v3-s1-namespace
kayg:archive/flaky/rows-drop-fixed
kayg:archive/flaky/rows-actions
kayg:archive/feat/tiering-v3-reader
kayg:archive/feat/tiering-v3-roots
kayg:archive/flaky/rows
kayg:sim/bm15-final
kayg:sim/bm15-fix
kayg:sim/bm15-bis-932
kayg:sim/bm15-bis-909
kayg:sim/bm15
kayg:sim/bm15-bis-887
kayg:perf/tiering-option-b
kayg:port/style-3
kayg:port/style-2
kayg:port/style
kayg:fix/sw-lazy-precache
kayg:fix/vim-w-waits-for-save
kayg:fix/signout-test-races
kayg:fp-scratch/all
kayg:sim/bm15-first-paint
kayg:archive/bm15/rows-drop
kayg:archive/bm15/rows-actions
kayg:fix/palette-snippet-contrast
kayg:archive/bm15/rows
kayg:archive/bm15/hidden
kayg:archive/plan/save-log-durable-entry
kayg:mock/money-fix2
kayg:archive/fix/e2e-data-on-ram
kayg:mock/appearance-all
kayg:mock/pill-press
kayg:archive/docs/design-consistency
kayg:mock/auto-swipes
kayg:mock/mail-actions
kayg:archive/feat/mail-p1
kayg:mock/money-static
kayg:archive/review/standards-917
kayg:archive/docs/engineering-standards
kayg:perf/tiering-761-fix
kayg:mock/type-audit
kayg:mock/third-pane
kayg:feat/contacts-import-v2-s1
kayg:perf/executor-hot-path
kayg:archive/port/hidden-blocks
kayg:archive/port/devices
kayg:scratch/executor-on-894
kayg:scratch/executor-spans2
kayg:scratch/executor-spans
kayg:train/2026-11-03-bm14c
kayg:archive/port/rows-drop
kayg:feat/tiering-761-d-scale
kayg:feat/tiering-761-c-index
kayg:feat/tiering-761-b-reader
kayg:archive/review/sharing-pr3-review-9fec3d1f
kayg:train/2026-11-03-bm14b
kayg:perf/ports-lazy-budgets
kayg:feat/tiering-761-a-migration
kayg:train/2026-11-03-bm14
kayg:train/2026-11-03-bm12
kayg:archive/review/sharing-pr3-review
kayg:archive/feat/sharing-s1-pr3
kayg:train/2026-11-03-bm11
kayg:archive/feat/imap-notes-fetch
kayg:train/2026-11-03-bm10
kayg:archive/review/sharing-pr3-review-code
kayg:archive/plan/previews-865
kayg:train/2026-11-02-bm9
kayg:archive/port/port-attachments-3
kayg:archive/port/contacts-merge
kayg:fix/motion-audit-859
kayg:train/2026-11-02-bm8
kayg:archive/scratch/bm8-prep
kayg:archive/port/port-pickers
kayg:archive/port/port-tables-2
kayg:archive/port/port-tables
kayg:archive/feat/sharing-s1-pr3-code
kayg:archive/scratch/bm7-fixed
kayg:train/2026-11-02-bm7
kayg:archive/fix/parallel-test-flakes-code-minipc01
kayg:train/2026-11-02-bm6
kayg:docs/imap-766-readonly-slice
kayg:feat/dav-recorder-v3
kayg:research/788-diagnosis
kayg:archive/fix/parallel-test-flakes
kayg:archive/perf/pr792-cold-index-edit
kayg:docs/sharing-slice-1
kayg:archive/docs/imap-766-plan-v2
kayg:feat/dav-recorder-v2
kayg:archive/docs/dav-recorder-v2-plan
kayg:spike/imap-766-s0-cases
kayg:archive/fix/undo-768
kayg:feat/dav-recorder
kayg:archive/docs/contacts-import-v2-plan
kayg:archive/feat/calendar-ical-converter
kayg:feat/contacts-import
kayg:perf/cold-growth-on-764
kayg:perf/cold-growth-on-tiering
kayg:archive/docs/tasks-writes-v2-plan
kayg:archive/docs/calendar-backend-v2-plan
kayg:archive/feat/contacts-companion-pure
kayg:feat/tasks-set-status
kayg:feat/tasks-move-reorder
kayg:archive/docs/carddav-writes-v2-plan
kayg:archive/feat/calendar-v2-s1-containment
kayg:feat/tasks-delete-promote-duplicate
kayg:archive/feat/dav-transport
kayg:archive/fix/carddav-rebuild-r1
kayg:archive/fix/carddav-retention-r1
kayg:feat/carddav-writes
kayg:perf/quota-on-tiering
kayg:perf/quota-simple
kayg:perf/cold-growth-on-quota-stack
kayg:feat/calendar-identity
kayg:feat/calendar-event-parser
kayg:feat/calendar-props-maps
kayg:port/glass-when-ring
kayg:feat/tiering-761-s1
kayg:wip/10by32-01-impl-759b-scratch-20261030
kayg:wip/6by32-01-bm3-webkit-pause-20261030
kayg:wip/10by32-01-bm3-chromium-pause-20261030
kayg:wip/6by32-01-tier-761-s1-pause-20261030
kayg:spike/imap-766-s0
kayg:wip/6by32-02-calternal-pause-20261030
kayg:wip/8by64-01-review-688-pause-20261030
kayg:wip/6by32-01-verify-744-pause-20261030
kayg:wip/6by32-01-verify-742-pause-20261030
kayg:fix/private-staging-759b
kayg:wip/6by32-01-review-748-pause-20261030
kayg:wip/6by32-01-review-733c-pause-20261030
kayg:wip/6by32-01-review-733b-pause-20261030
kayg:wip/6by32-01-perf-idle-8-pause-20261030
kayg:wip/6by32-01-perf767-base-pause-20261030
kayg:wip/6by32-01-perf767b-767-pause-20261030
kayg:wip/6by32-01-perf767b-764-pause-20261030
kayg:wip/6by32-01-perf767-767-pause-20261030
kayg:wip/6by32-01-perf767-764-pause-20261030
kayg:wip/6by32-01-lists-b-pause-20261030
kayg:wip/6by32-01-ids-verify5-pause-20261030
kayg:wip/6by32-01-ids-verify4-pause-20261030
kayg:review/calendar-month
kayg:wip/10by32-02-undo-768-20261030
kayg:test/ids-verify3
kayg:wip/10by32-02-bm3-chromium-20261030
kayg:wip/10by32-01-review-753-20261030
kayg:wip/10by32-01-perf-idle-2-20261030
kayg:wip/10by32-01-bm2-webkit2-20261030
kayg:plan/759b-staging
kayg:train/2026-10-30-bm2
kayg:review/758b-tests
kayg:review/758-tests
kayg:review/764d-tests
kayg:review/767b-tests
kayg:review/preview-2026-10-29
kayg:review/767-tests
kayg:docs/tiering-731-plan
kayg:wip/c6b02-when2
kayg:wip/c6b02-tasks-create-fix5
kayg:wip/c6b02-settings-frost-mock
kayg:wip/c6b02-settings-frost-base
kayg:wip/c6b02-settings-frost
kayg:wip/c6b02-ring
kayg:wip/c6b02-review-733d
kayg:wip/c6b02-bm1-full-a
kayg:wip/compute02-when-field
kayg:wip/compute02-webkit-lists-repro
kayg:wip/compute02-train-bl2-dev
kayg:wip/compute02-dev-green-pw164
kayg:docs/deploy-plan
kayg:review/764c-tests
kayg:review/764b-tests
kayg:review/748g-tests
kayg:review/764-tests
kayg:review/759b-tests
kayg:fix/storage-owner-liveness-642
kayg:fix/storage-fix-7
kayg:wip/compute02-storage-fix-7
kayg:review/759-tests
kayg:feat/tiering-731
kayg:wip/tiering-731-first-attempt
kayg:wip/compute02-storage-fix-1
kayg:review/754g-tests
kayg:perf/idle-honest-2
kayg:review/754f-tests
kayg:review/754e-tests
kayg:review/755-tests
kayg:review/754d-tests
kayg:review/754c-tests
kayg:review/754b-tests
kayg:review/754-tests
kayg:fix/storage-private-tmp-642-dev
kayg:wip/compute02-verify-750
kayg:test/ids-verify5
kayg:test/ids-verify4
kayg:fix/storage-exact-file-quarantine-642
kayg:wip/compute02-verify-740
kayg:perf/one-flush-save
kayg:review/calendar-static
kayg:wip/compute02-verify-737
kayg:review/indexing-ring
kayg:review/when-field-2
kayg:wip/compute02-review-733
kayg:proto/block-identity-2-review
kayg:proto/block-identity-review
kayg:wip/c6b02-tc-design
kayg:review/when-field
kayg:issue/tasks-create-ids
kayg:issue/tasks-create
kayg:review/combined
kayg:wip/compute02-review-combined
kayg:review/task-polish
kayg:review/top-buttons
kayg:review/q1-q5
kayg:train/2026-10-26-bl2
kayg:archive/wt-398h
kayg:archive/train-bm-proptest-seed
kayg:archive/integ325-293
kayg:archive/integ325-ci
kayg:archive/client-auth-review-baseline
kayg:archive/wt-sim-4853
kayg:archive/wt-sim-4811
kayg:archive/wt-448m
kayg:archive/wt-398a-allocator
kayg:issue/calendar-adr
kayg:archive/old/train/2026-10-23bk2
kayg:archive/old/train/2026-10-23bk
kayg:issue/469-mockup-9a
kayg:issue/smart-tasks-mockup
kayg:issue/469-menus
kayg:issue/652-signout-flake
kayg:issue/652-history-fix7
kayg:issue/652-history-fix6
kayg:archive/old/issue/spring-check-perf
kayg:issue/spring-check-perf
kayg:issue/659-rename-fast
kayg:archive/old/train/2026-10-21ar
kayg:issue/search-hardening-3
kayg:issue/652-history-fix5
kayg:issue/660-port-sheets-glass
kayg:issue/652-history-fix4
kayg:issue/652-history-fix3
kayg:issue/652-history-fix2
kayg:issue/652-history-flake
kayg:train/2026-10-21an
kayg:issue/settings-admin-port
kayg:issue/search-port
kayg:train/2026-10-20am
kayg:issue/storage-split-fix2
kayg:issue/storage-split
kayg:archive/old/issue/folder-ids-fix
kayg:train/2026-10-20al
kayg:archive/old/issue/folder-ids
kayg:train/2026-10-20ak
kayg:issue/tables-mockup
kayg:train/2026-10-19aj
kayg:train/2026-10-19ai
kayg:issue/469-merge-fixes
kayg:issue/sidebar-band
kayg:archive/old/issue/608-settings-spec
kayg:train/2026-10-19ah
kayg:issue/swipe-offscreen
kayg:train/2026-10-19ag
kayg:archive/old/issue/590-nlp-adr
kayg:archive/old/issue/587-event-after-write-2
kayg:train/2026-10-19af
kayg:archive/old/issue/587-event-after-write
kayg:issue/469-pill-room-c
kayg:issue/469-pill-room
kayg:train/2026-10-19ae
kayg:issue/469-narrow-handle
kayg:issue/397-ios-swipe-2
kayg:archive/old/issue/adrs-photos-files-tasks
kayg:issue/469-desk-fixes
kayg:archive/old/issue/auto-update-adr
kayg:issue/469-filter-gap
kayg:issue/469-port-1b
kayg:issue/442-opacity-flake
kayg:archive/397-ios-swipe-2
kayg:issue/327-web-fast-3
kayg:archive/old/issue/469-port-1
kayg:issue/469-port-1
kayg:issue/327-web-fast-2
kayg:archive/old/issue/327-web-fast
kayg:archive/old/issue/425-stt-bench-vq1
kayg:archive/old/issue/445-no-bleed
kayg:archive/old/issue/400-swipe-mockup-2
kayg:issue/426-client-review
kayg:issue/426-client-2
kayg:issue/426-client
kayg:archive/old/issue/476-safe-area-lab
kayg:archive/445-top-light-2
kayg:archive/old/issue/445-top-light
kayg:issue/471-blocks-mockup
kayg:archive/old/issue/448-links-app-2
kayg:archive/old/issue/448-links-app
kayg:archive/old/issue/398-cold-links
kayg:issue/434-442-small-2
kayg:issue/434-442-small
kayg:archive/old/issue/398-unload
kayg:archive/old/issue/445-bottom-band
kayg:issue/445-bottom-band
kayg:issue/351-rem-3
kayg:archive/312-views-mockup
kayg:issue/351-rem-2
kayg:issue/351-rem
kayg:archive/old/issue/327-first-note
kayg:issue/395-width-phone
kayg:archive/old/issue/327-typing
kayg:issue/396-ios-edges
kayg:issue/397-ios-swipe
kayg:archive/398-allocator
kayg:archive/old/issue/327-notes-index
kayg:issue/345-347-contrast-empty-2
kayg:archive/old/issue/44-arenas
kayg:issue/44-arenas
kayg:archive/integ325
kayg:archive/old/issue/327-perf-harness
kayg:archive/old/issue/44-thp
kayg:issue/44-thp
kayg:archive/old/issue/285-sticky-pills
kayg:archive/old/issue/44-trim-3
kayg:issue/44-trim-3
kayg:archive/old/issue/165-cards
kayg:archive/old/issue/165-picker-2
kayg:archive/old/issue/212-multi-select
No reviewers
Labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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!871
Loading…
Reference in a new issue
No description provided.
Delete branch "plan/previews-865"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Attachment previews currently have no isolated generation pipeline. This plan defines P1–P6 from #865: sandboxed decoders, asynchronous resumable jobs, two WebP sizes, batch metadata, derived storage, device caching and native-library packaging.
Design: docs/plans/0865-previews.md. Backend implementation follows BM8 in one PR; cards follow in the pictures port (#846). No implementation code in this PR.
Decisions: rootless Bubblewrap namespaces, Landlock, seccomp and process rlimits, without procfs or per-job cgroups. Default-off generation requires a final-production-image probe and both-architecture package gates before enablement. Bounded header fill and resumable backfill cover existing/outside-written attachments; verified content hashes plus generation checks prevent stale reuse. Retain attachments.meta and add list/peek/open descriptors. FFmpeg uses a minimal LGPL library build; HEIC stays independently off pending codec/patent clearance.
Preview work never gates uploads or note writes. Keep the approved type icon until ready, without moving text. Initial latency targets are unvalidated; implementation gates and measurement conditions are specified in the plan.
Open risks: procfs-free native decoder paths and outer-container limits still require final-image verification; minimal native closures require both-architecture checks. Coordinate the additive metadata contract with #846. Artifacts and run results belong in issue/PR comments only.
Refs #865. Never merge this PR automatically.
Validation at head
6c40b72ab5c6c9e8cc93b9bf98998d3e1d8cdae8:git diff --check origin/dev...HEADpassed;git status --shortis empty. Onlydocs/plans/0865-previews.mdchanged. No builds or tests run for this plan-only PR, per the control-host rules. Performance numbers in the plan are proposed gates, not run results. No merge performed.verdict: changes needed
must-fix
Make the sandbox and resource-limit contract match rootless production. On dev-01, Podman is 5.8.9, rootless, cgroup v2 with the systemd manager. The production image was not present there, so I used Debian bookworm-slim with the same
keep-id:uid=10001,gid=10001mapping and Bubblewrap 0.12.0 from the pinned Nixpkgs.bwrap --unshare-allwith a private tmpfs root succeeded. Its--proc /procmount failed withEPERM. Landlock ABI 6 successfully denied a file read, a seccomp filter successfully deniedsocket(), and loweringRLIMIT_CPU,RLIMIT_AS,RLIMIT_FSIZEandRLIMIT_NOFILEworked. Creating a child under/sys/fs/cgroupfailed; the cgroup was not delegated into the container. Please specify the exact Quadlet/systemd delegation and outer CPU/memory limits, then test child-cgroup creation in the final image. If that cannot be delegated, replace the per-job cgroup requirement with the process limits and outer service cap that are actually available, update the stated 512 MiB/1 GiB guarantees, and keep previews disabled until the chosen gate passes. Test the worker root without/procor show a permitted way to mount it. I did not test nsjail; the planned Bubblewrap path is viable with the noted procfs limitation.Define metadata backfill and source invalidation. #846 currently gets dimensions through
attachments.metaby reading each referenced file, up to 200 paths, before the first picture draw. This plan changes that action to cached descriptors. It does not say how the cache gets dimensions for existing attachments or files written outside the upload action. Add an initial bounded backfill or a fast header-only fill in thenotes.list/peekbatch so oriented dimensions are present before #846 mounts boxes; do not wait for PDF decoding. Also make the path-to-content identity rule explicit.crates/attachments/src/place.rs::existingcurrently treats a matching indexed hash plus matching length as a duplicate, so a same-size replacement can reuse stale metadata or return the wrong “Already uploaded” path. Persist a file-generation fingerprint, invalidate and rehash when it changes, and check the source identity before and after decoding and before serving. Do not rely on watcher events alone.Pin decoder builds that implement the stated loader, protocol and licensing policy. I evaluated the exact flake nixpkgs pin on x86_64-linux and aarch64-linux. The pin already has
pdfium8066 for both architectures, and the libvips package is namedvips(8.18.7), notlibvips. The defaultvipsderivation brings in optional loaders including libarchive, ImageMagick, libraw, librsvg, OpenSlide and Poppler, beyond the plan's allowlist. The defaultffmpeg9.0.1 enables network support and GPL components including x264/x265, so it does not meet “local file/FD protocols only” as packaged.libheifhas thelibde265decoder on both architectures, but its derivation also includes x265; the LGPL package metadata does not settle HEVC patent coverage. Please name thepdfiumpackage already in the pin, define a restrictedvipsloader set and an FFmpeg build with network protocols and unneeded GPL encoders disabled, and assert the final loader/protocol/decoder lists on both architectures. Keep HEIC independently unavailable with the icon until its codec and patent decision is cleared.should-fix
Make the production enablement gate explicit. The first backend PR is broad: several decoder stacks, queue persistence and reconciliation, metadata APIs, cache eviction, two Linux closures, the rootless image profile and a new performance harness. P6 does call for one backend PR, so keep that boundary if it is intentional, but add an operator-controlled, default-off preview switch and state that production stays off until the final-image sandbox and package gates pass. Document which formats are enabled when an optional codec is absent.
Treat the latency numbers as initial targets, not validated gates. The 2s/3s/5s no-backlog targets look plausible for a 320 output, but 20 samples make p95 effectively the second-slowest sample. Increase repetitions before using p95 as a release gate, or label it diagnostic until a larger run. Include worker cold start and the production source-storage path in the measurement; originals are on the data root while preview state is on SSD per
docs/storage.md. The plan correctly keeps functional write/typing checks barrier-based and puts timing in the performance harness.fine
Keep the P2 same-slot icon and no processing text, independent 320/1280 readiness, per-user content/recipe storage keys, immediate access revocation with later GC, and the async journal-to-queue path. The batched additive descriptors for list/peek/open are the right integration for #846, and keeping cards in the pictures port follows P6. Keep the write-stall barriers, queue fairness cases and storage-backup exclusion as gates.
Revised in
5d3a4bbe254a44927ad94d100de597c8995f1440, addressing every finding in the review, in this one design revision:Rootless sandbox/resource contract: removed child cgroups and all procfs mounts. Use Bubblewrap namespaces, mandatory Landlock/seccomp, seekable inherited-FD adapters, no helper scratch files, RLIMIT_AS 512 MiB, CPU/FD/core/file limits, parent deadlines and enforced pipe-byte caps. Two slots imply at most 1 GiB decoder address space, not a hard pool RSS promise. Outer Quadlet Podman limits are explicitly 3 GiB/no additional swap/4 CPUs. The enablement gate must run the probe and real fixtures inside the final production image, with the production UID mapping/security profile and no /proc, checking both allowed work and denied operations. This gate is planned, not claimed to have passed.
Backfill and invalidation: added resumable pages of existing indexed files and bounded Photos/Documents discovery for outside writes, using the existing queue window. Fresh list/peek/open/meta batches can fill missing oriented dimension hints from at most 64 KiB per file, without PDF/native decoding. Persist blake3 and device/inode/size/nanosecond mtime/ctime fingerprints; the fingerprint validates a previously hashed generation, while blake3 remains content identity. Changed or unverifiable generations invalidate access and trigger background rehash. Check before/after decode, publication and serving, including 304s. Repair place::existing and attachments.check so matching length cannot return a false “Already uploaded”; stale candidates are misses without a write-path rehash wait. Added restored-mtime, replacement and missed-watcher cases.
Minimal packages/licensing: name the pinned pkgs.pdfium 8066 and pkgs.vips 8.18.7, with explicit loader exclusions and V8/XFA disabled. FFmpeg 9.0.1 is a restricted LGPL library-only build: disable-everything/autodetect/network/GPL/nonfree/programs, then enable only listed demuxers/parsers/video decoders and required libraries. Custom seekable FD AVIO removes CLI/protocol/procfs dependencies. No encoders, muxers, filters, network protocols, x264 or x265; GPL FFmpeg is unnecessary for posters despite Calternal being AGPLv3. Assert actual component/closure lists on both architectures. Optional HEIC uses decoder-only libheif/libde265, no x265, and stays separately off until codec/patent clearance and its fixture gate. FFmpeg HEVC remains disabled.
Enablement/scope: retain P6's single backend PR intentionally. CALTERNAL_PREVIEWS defaults off; explicit operator enablement follows final-image and package gates. Missing optional HEIC/HEVC keeps the icon while the listed supported image/PDF/video/text formats remain eligible. Isolation failures disable generation rather than weakening it. Kept same-slot icons, independent sizes, async queue, fairness/write-stall tests and backup exclusions.
Latency targets: explicitly unvalidated. Twenty samples are diagnostic only; at least 200 per type/cache cohort precede promotion to a release gate. Include worker cold start, source validation, data-root/HDD originals and SSD state. Report peak RSS separately from configured address-space limits. Functional checks remain barrier-based.
Validation:
git diff --check origin/dev...HEADpassed;git status --shortis empty. This revision changes only the plan. No builds, decoder probes, performance runs or implementation tests were run, and no run results were added to the document. No merge performed. Remaining verification belongs to the first implementation PR's final-image/package gates.kayg referenced this pull request2026-11-05 23:21:11 +00:00
housekeeping #1009: rebased+green, left open for review.
rebased preview plan; proposal retained.
head:
7496354b17a3f75bebe55e8f90d9a7847babadbd. rebased onto devcd7f84432febfc63b788fbb9b9f9950452982d74and pushed with the original exact force-with-lease.validation on the Mac VM, through Nix and the shared Mac lock/slot: root
bun install --frozen-lockfile; inapps/web,bun run check,bun run lint,bun run build,bun run test;PERF_DIST=<worktree>/apps/web/dist bash perf/web.sh --bundle-only --gate. all passed. this documentation-only branch has no targeted browser specs or Rust implementation changes. exact commands, logs, and dev bundle control.original-head missing-commit/patch inventory, file
pr-871.md.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.