Claude
62e9bc67f1
feat(media): stream artifacts over HTTP with Range support
...
Videos and audio can be hundreds of megabytes. Artifacts only travelled as
base64 inside RPC calls, capped at 10 MiB and held whole in memory, so media
could neither be uploaded, played with seeking nor produced by media jobs.
- ArtifactStore gains stat, createReadStream (inclusive byte ranges),
putStream (size cap enforced while writing, real SHA-256) and an optional
localPath so ffmpeg can read stored files in place. LocalArtifactStore
implements them with the same safety as before (O_EXCL, O_NOFOLLOW, 0600)
and now validates space ids and keys before building paths.
- storeArtifactStream / storeArtifactFromFile store a stream or a job's
output file as an artifact row, with width, height, duration and parent,
and remove the blob again if the row cannot be written.
- GET /api/artifacts/:id serves an artifact with Range/206/416, ETag,
inline disposition for media and attachment otherwise (safe RFC 6266
filenames), nosniff and same-origin CORP. Authorization matches
artifacts.get: the owner's artifact of an active bot thread or group,
with membership of the artifact's space (media elements cannot send the
space header; an explicit header must name the same space).
- POST /api/artifacts takes a raw streamed body with the target and name in
the query, authorized like artifacts.create, with the MIME allowlist and
the per-kind caps checked from Content-Length and again while writing.
- The API CSP allows media from the app origin and blob URLs.
- Web: artifactUrl(artifactId) and uploadArtifactFile for the UI.
Tests cover the streaming store, range parsing, filename sanitizing, the
file helper, and a Postgres suite for both routes: ranges, caching, other
users, shared-space members, other spaces, archived threads, signed-out
requests and upload limits including chunked bodies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
2026-10-03 13:31:39 +00:00
..
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 06:20:51 +00:00
2026-09-22 06:20:51 +00:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 13:31:39 +00:00
2026-10-03 13:31:39 +00:00
2026-10-03 13:31:39 +00:00
2026-10-03 13:31:39 +00:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-22 06:20:47 +00:00
2026-09-22 06:20:47 +00:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-23 22:09:49 +02:00
2026-09-23 22:09:49 +02:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 06:20:49 +00:00
2026-09-22 12:29:25 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 14:32:18 +02:00
2026-09-22 14:32:18 +02:00
2026-09-22 06:21:08 +00:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 14:32:18 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-21 22:52:04 +00:00
2026-10-03 06:44:20 +02:00
2026-09-21 22:52:04 +00:00
2026-09-20 17:15:16 +02:00
2026-09-21 22:52:04 +00:00
2026-09-23 22:09:49 +02:00
2026-09-23 22:09:49 +02:00
2026-09-23 22:09:49 +02:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-09-23 22:09:49 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-23 22:09:49 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-23 22:09:49 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-23 22:09:49 +02:00
2026-09-22 04:37:18 +00:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 07:04:29 +00:00
2026-09-22 07:04:29 +00:00
2026-09-22 06:21:08 +00:00
2026-09-22 06:21:08 +00:00
2026-09-20 17:15:16 +02:00
2026-10-03 13:31:39 +00:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 07:06:21 +00:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-23 22:09:49 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-25 18:42:45 +02:00
2026-09-25 18:42:45 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-22 12:29:25 +02:00
2026-09-22 12:29:25 +02:00
2026-09-23 22:09:49 +02:00
2026-09-23 22:09:49 +02:00
2026-09-22 06:22:13 +00:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 13:04:16 +00:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-22 14:35:36 +02:00
2026-09-22 14:35:36 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-10-03 06:44:20 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00
2026-09-20 17:15:16 +02:00