GET /enhance/jobs without a path now answers the jobs manager (FVR #99):
every photo's queued / running / unavailable jobs, plus ready / failed /
expired ones touched in the last 3 days, newest first, discarded and
approved hidden, at most 100. DB only; the poller keeps rows current.
An optional status=a,b filter applies to both forms.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Groundwork for Enhance "Animate" (#208): a video made from a photo.
- Version linking reads the XMP link from MP4 / MOV too (top-level uuid box
with the XMP UUID, mdat seeked over), at ingest and on Enhance approve.
- New kind `animated`, a derived clip (CLIP_KINDS): hidden behind the photo
like a version, but not counted in photo_version_counts / version_count,
never a display choice (400 clip_not_displayable), and listed as `clips`
in GET /image/versions. Approve returns the clip entry.
- Templates whose imageapi:save is ImageApiSaveVideoVersion report
output "video" in /enhance/templates (no enhance.toml change). Previews
already relay ComfyUI's content type (video/mp4).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- error::ApiError (ResponseError): status + stable snake_case code +
display-safe message + optional details. From<anyhow>/From<diesel> and
into_http_internal_err become a 500 "internal" whose cause is logged,
never sent.
- JSON body, query and path parse failures, the Claims 401 and unknown
routes now answer in the format instead of actix's plain text.
- tags handlers return ApiResult with codes (invalid_tag_name,
tag_not_found, tag_name_taken, no_files, too_many_files,
nothing_to_change, tag_added_and_removed). The rename 409 keeps
existing_tag at the top level for older clients.
- Enhance's error_response builds through ApiError; its codes are
unchanged, and an internal error no longer sends its message.
- duplicates: eight 500s sent format!("{:?}", e) to the client.
Refs #202
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parse execution_start vs the end event from /history, store it when the
poller moves a job to ready/failed (never overwritten with null), and
return it as "run_ms" on every job endpoint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>