You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Implement on-demand original file serving endpoint #44
Path: the storage config's RootPath joined with MediaAsset.FilePath. Never build it from request input, and guard that the result stays under RootPath.
changed the title [-]5.7 Implement on-demand original file serving endpoint[/-][+]Implement on-demand original file serving endpoint[/+]on May 12, 2026
The originals are whatever the NAS holds: JPEG, HEIC, MOV and possibly RAW.
What limits the solution:
Most browsers cannot render HEIC or RAW at all.
Every display path in the UI already uses proxies: thumbnail, preview and video, all auto-oriented to upright at ingest.
The asset DTO already reports upright width/height.
Options:
Byte-identical stream. Serve the file exactly as stored; the EXIF orientation stays inside it.
How: content type from the extension, ETag from ContentHash, range requests via Results.Stream, so the endpoint is cheap and cacheable.
Cost: a client that draws the original itself (e.g. on a canvas) must apply the EXIF orientation. <img> already does for JPEG, since image-orientation: from-image is the browser default.
Rotate on the server. Decode, rotate by Metadata.Orientation, re-encode.
Cost: the result is no longer the original. JPEG re-encoding is lossy; HEIC, RAW and video can't be done this way; and it costs CPU per request, or a cached full-size rendition.
That rendition is a full-resolution FullPreview, i.e. a new proxy type, not an originals endpoint.
Byte-identical, plus orientation in the asset DTO for clients that draw originals themselves.
Cost: a contract field with no caller today, which the first-caller rule rules out until one exists.
Change the pattern: no originals endpoint in v1.0. If the UI ever needs more than the 1920 px preview, add a larger upright proxy through the existing proxy endpoint (Implement proxy file serving endpoint #43). Originals stay a later "download" feature.
Cost: no way to fetch the original file in v1.0.
Recommendation: first decide whether v1.0 needs this at all.
If a v1.0 feature downloads originals: option 1. It is the only option that keeps "original" true, and display already has its upright path through the proxies.
No issue asks to download, export or open the original.
Hard to reverse: the public contract of GET /api/v1/assets/{id}/original.
Once clients rely on byte identity (the ETag equals the content hash, and the file can be saved as is), switching to rotated pixels would need a different endpoint.
If the UI needs more than the 1920 px preview, the answer is a larger upright proxy through the existing proxy endpoint (Implement proxy file serving endpoint #43), not this endpoint.
Implement on-demand original file serving endpoint #44 moves to post-1.0 and back to needs-triage, to be picked up again when a feature (e.g. "download original") gives it a first caller. The orientation question goes with it; the note recommends a byte-identical stream (option 1) for that day.
Activity
[-]5.7 Implement on-demand original file serving endpoint[/-][+]Implement on-demand original file serving endpoint[/+]bitbiter-dev commentedon Oct 17, 2026
Design note
Written as the architect, in the #261 pilot of
docs/agents/design-process.md.Problem and constraints: serve an asset's original file from the NAS.
VisibleTo), otherwise404.RootPathjoined withMediaAsset.FilePath, kept insideRootPath. It goes throughIOriginalStorefrom refactor(api): Narrow read-only storage interfaces instead of ReadOnlyFileSystem #251, notIFileSystem.width/height.Options:
ETagfromContentHash, range requests viaResults.Stream, so the endpoint is cheap and cacheable.<img>already does for JPEG, sinceimage-orientation: from-imageis the browser default.Metadata.Orientation, re-encode.FullPreview, i.e. a new proxy type, not an originals endpoint.orientationin the asset DTO for clients that draw originals themselves.Recommendation: first decide whether v1.0 needs this at all.
First caller: none found.
Hard to reverse: the public contract of
GET /api/v1/assets/{id}/original.Decision needed:
bitbiter-dev commentedon Oct 17, 2026
Decision
Option 4: no originals endpoint in v1.0. Decided by the maintainer, 2026-10-17, on the design note above.
needs-triage, to be picked up again when a feature (e.g. "download original") gives it a first caller. The orientation question goes with it; the note recommends a byte-identical stream (option 1) for that day.