Commits
Add media-src 'self' https: to CSP so video elements load from the
cross-origin Blossom host without grey-boxing in production. Fix the
post-save state.images remap in saveActiveDraft to carry duration_secs,
video flag, and phase:"ready" (matching loadDraft hydration shape) so
the XOR guard, video tile, and duration gates survive a save. Add a
pre-save guard that blocks saving while a video is still processing,
and a waitJobDone helper in the test to drain in-flight jobs before
TempDir cleanup (de-flaking TestVideoUploadQueueFull429). Sharpen the
attachVideo busy-flash to distinguish "already have a video" from
"already have images".
- Img.SizeBytes carries the canonical object size through all construction sites
(assembleImages add/video-ref branch, dispatchTargets, srcImgs in interact)
- dispatchTargets rebuilds Img from the store row (mime/dim/duration/size) and
gates video fetch to rows within FetchCap, mirroring assembleImages' policy
- gateVideo uses SizeBytes (fallback len(Bytes)) so retry/fire gates fire
correctly even without in-memory bytes; drops dead zero-branch
- Fresh multipart video on /api/post and draft create/update returns 400 with
a pointer to the async pipeline (/api/media/video)
- Interact source-media re-host loop skips video with continue (best-effort)
- PlanMediaFit skips video/ mimes (VideoGate covers them separately)
- Tests: TestGateVideoUsesCanonicalSize; updated gateVideo table for new error
strings; TestAPIPostVideoReferenceOverFetchCapSkipsFetch;
TestAPIPostFreshVideoRejected
Per-route read/write deadline extension (30 min) prevents the global
60 s ReadTimeout from killing 1 GB uploads. Runner.Full() enables a
pre-body 429 before receiving the upload. Disk-full io.Copy errors
now map to 507 (not 400) without leaking filesystem paths. Shared
DefaultWorkdir() in videojob eliminates the two-place fallback
divergence; main.go logs and skips the pipeline when MkdirAll fails.
Tests cover the 429 queue-full path and the missing-file-part 400.
- Bound Probe with a 1-minute context to prevent wedge-forever hangs
- Add maxPending=3 cap + ErrBusy (→ 429); Submit consumes inPath unconditionally
- Evict terminal jobs older than 1 hour from the registry inside Submit
- Job gains unexported doneAt; set in fail() and StateDone transition
- Replace sleep-based TestJobsSerialize with gateTC for deterministic serialization
- Add TestSubmitRejectsWhenFull covering cap enforcement and input cleanup
- Package/SweepWorkdir/newID doc improvements; rand.Read silent-error annotation
Guard maybeAppendQuotedCard against double-appending a .pv-quoted card when
_renderSinglePost and the .then post-processing both call it on reply/quote
previews. Add an isStale callback to threadPreview so late fetch responses
never overwrite a newer render. Remove the now-unreachable mediaOverflow flag
(hasMedia already covers it) and consolidate previewMedia(p) into one call.
Add media-src 'self' https: to CSP so video elements load from the
cross-origin Blossom host without grey-boxing in production. Fix the
post-save state.images remap in saveActiveDraft to carry duration_secs,
video flag, and phase:"ready" (matching loadDraft hydration shape) so
the XOR guard, video tile, and duration gates survive a save. Add a
pre-save guard that blocks saving while a video is still processing,
and a waitJobDone helper in the test to drain in-flight jobs before
TempDir cleanup (de-flaking TestVideoUploadQueueFull429). Sharpen the
attachVideo busy-flash to distinguish "already have a video" from
"already have images".
- Img.SizeBytes carries the canonical object size through all construction sites
(assembleImages add/video-ref branch, dispatchTargets, srcImgs in interact)
- dispatchTargets rebuilds Img from the store row (mime/dim/duration/size) and
gates video fetch to rows within FetchCap, mirroring assembleImages' policy
- gateVideo uses SizeBytes (fallback len(Bytes)) so retry/fire gates fire
correctly even without in-memory bytes; drops dead zero-branch
- Fresh multipart video on /api/post and draft create/update returns 400 with
a pointer to the async pipeline (/api/media/video)
- Interact source-media re-host loop skips video with continue (best-effort)
- PlanMediaFit skips video/ mimes (VideoGate covers them separately)
- Tests: TestGateVideoUsesCanonicalSize; updated gateVideo table for new error
strings; TestAPIPostVideoReferenceOverFetchCapSkipsFetch;
TestAPIPostFreshVideoRejected
Per-route read/write deadline extension (30 min) prevents the global
60 s ReadTimeout from killing 1 GB uploads. Runner.Full() enables a
pre-body 429 before receiving the upload. Disk-full io.Copy errors
now map to 507 (not 400) without leaking filesystem paths. Shared
DefaultWorkdir() in videojob eliminates the two-place fallback
divergence; main.go logs and skips the pipeline when MkdirAll fails.
Tests cover the 429 queue-full path and the missing-file-part 400.
- Bound Probe with a 1-minute context to prevent wedge-forever hangs
- Add maxPending=3 cap + ErrBusy (→ 429); Submit consumes inPath unconditionally
- Evict terminal jobs older than 1 hour from the registry inside Submit
- Job gains unexported doneAt; set in fail() and StateDone transition
- Replace sleep-based TestJobsSerialize with gateTC for deterministic serialization
- Add TestSubmitRejectsWhenFull covering cap enforcement and input cleanup
- Package/SweepWorkdir/newID doc improvements; rand.Read silent-error annotation
Guard maybeAppendQuotedCard against double-appending a .pv-quoted card when
_renderSinglePost and the .then post-processing both call it on reply/quote
previews. Add an isStale callback to threadPreview so late fetch responses
never overwrite a newer render. Remove the now-unreachable mediaOverflow flag
(hasMedia already covers it) and consolidate previewMedia(p) into one call.