Skip to content

feat(media): public media CRUD API routes (/api/media/v1)#69

Merged
ABB65 merged 2 commits into
mainfrom
feat/media-api-routes
Jun 18, 2026
Merged

feat(media): public media CRUD API routes (/api/media/v1)#69
ABB65 merged 2 commits into
mainfrom
feat/media-api-routes

Conversation

@ABB65

@ABB65 ABB65 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Phase 2 — Public media CRUD API (/api/media/v1/...)

Built on the merged Phase 1 scope foundation (#67). (Supersedes #68, which GitHub auto-closed when the stacked base branch was deleted on #67 merge. Same code; now targets main directly — diff is Phase 2 only.)

Routes — /api/media/v1/[projectId]/assets/

Op Method Scope Notes
list GET assets media:read search / tags / type + page/sort
get GET assets/:id media:read project-scoped
upload POST assets media:write multipart binary or JSON {url} (SSRF-guarded)
update PATCH assets/:id media:write alt / tags / focal point
delete DELETE assets/:id media:write
bulk POST assets/bulk media:write delete/tag, ≤50, never cross-project

Design

  • resolveMediaApiContext — one gate per route: Bearer-key → project match → scope → per-key hourly rate limit → plan feature → ee media provider (mirrors the MCP Cloud proxy gate order; 503 in Community Edition).
  • withMediaUrls — assets get the CDN delivery URL + per-variant URLs (raw storage paths kept). Public no-auth browser delivery (custom domain) stays ee/roadmap.
  • Upload reuses Phase 1's SSRF-hardened fetchRemoteMedia + the same MIME/size/storage-quota pipeline as the session route.

Local-files note

Only upload needs the bytes → runs where files are (Local MCP / CI). list/get/update/delete/bulk work over MCP Cloud too.

Checks

typecheck ✅ · lint ✅ · 688 tests green (unit + integration + nuxt). Gate decisions + URL building unit-tested. Full per-route integration tests + scope UI (CDNPanel) are Phase 3.

Contentrain added 2 commits June 18, 2026 21:02
The external media management surface external agents/CI use to upload
to Studio CDN and manage assets, built on the Phase 1 scope foundation.

- `server/utils/media-api.ts` — `resolveMediaApiContext`: the single gate
  every route runs through (Bearer-key validation, project match, scope,
  per-key hourly rate limit, plan feature, ee media provider; mirrors the
  MCP Cloud proxy gate order; 503 in Community Edition).
- `server/utils/media-url.ts` — `withMediaUrls` decorates assets with the
  CDN delivery URL + per-variant URLs (raw storage paths kept).
- Routes under `/api/media/v1/[projectId]/assets/`:
  - GET `assets` (list, media:read), GET `assets/:id` (get, media:read)
  - POST `assets` (upload, media:write) — multipart binary OR JSON {url}
    (SSRF-guarded), shared validated pipeline + atomic storage reservation
  - PATCH `assets/:id` (update meta), DELETE `assets/:id`, POST `assets/bulk`
    (delete/tag, capped at 50, never cross-project) — all media:write

Only `upload` needs the file bytes (local → Local MCP/CI); list/get/
update/delete/bulk operate on ids + metadata, so they work over MCP Cloud
too. Helper unit tests cover the gate decisions + URL building (688 green).
Full per-route integration tests are a follow-up.
@ABB65 ABB65 merged commit 1267ae5 into main Jun 18, 2026
1 check passed
@ABB65 ABB65 deleted the feat/media-api-routes branch June 18, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant