openvibers/openvibe.contracts Commits
Describe Media multipart uploads in contracts and OpenAPI (#377)
Changes
@@@ -1,5 +1,9 @@# Changelog++## 0.359.0 — 2026-11-09++++- Media multipart uploads in contracts and OpenAPI++## 0.358.0 — 2026-11-09- Chat view preference (bubbles or room)@@@ -20,6 +20,7 @@"quotaClass": { "type": "string" },"events": { "type": "array", "items": { "type": "string" } },"implementedBy": { "type": "array", "items": { "type": "string" }, "description": "Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'." },++ "routeSchemas": { "type": "object", "description": "Input and output contract overrides for a route when one capability covers several operations.", "additionalProperties": { "type": "object", "additionalProperties": false, "properties": { "inputSchema": { "type": "string" }, "outputSchema": { "type": "string" } } } },"sensitive": { "type": "boolean", "description": "The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2)." }}}@@@ -365,6 +365,51 @@"compatibility": "backward","status": "active"},++ {++ "id": "media.upload",++ "version": "1.0.0",++ "owner": "media",++ "schema": "media/upload.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "media.upload-create",++ "version": "1.0.0",++ "owner": "media",++ "schema": "media/upload-create.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "media.upload-init",++ "version": "1.0.0",++ "owner": "media",++ "schema": "media/upload-init.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "media.upload-part",++ "version": "1.0.0",++ "owner": "media",++ "schema": "media/upload-part.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "media.upload-complete",++ "version": "1.0.0",++ "owner": "media",++ "schema": "media/upload-complete.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active"++ },{"id": "search.index-document","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-complete.v1.json",++ "title": "MediaUploadComplete",++ "description": "Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.",++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "content_hash": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" },++ "parts": { "type": "array", "items": { "type": "object", "required": ["part_number", "sha256"], "additionalProperties": false, "properties": { "part_number": { "type": "integer", "minimum": 1 }, "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" } } } }++ }++}nnew file mode 100644@@@ -0,0 +1,22 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-create.v1.json",++ "title": "MediaUploadCreate",++ "description": "Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.",++ "type": "object",++ "required": ["kind", "size_bytes", "multipart"],++ "additionalProperties": true,++ "properties": {++ "kind": { "type": "string", "enum": ["vod", "clip", "file", "thumbnail", "screenshot", "avatar", "asset"] },++ "size_bytes": { "type": "integer", "minimum": 1 },++ "multipart": { "const": true },++ "part_size": { "type": "integer", "minimum": 5242880, "description": "Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts." },++ "visibility": { "type": "string", "enum": ["public", "unlisted", "private"] },++ "mime_type": { "type": "string" },++ "filename": { "type": "string" },++ "content_hash": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" },++ "namespace": { "type": "string" },++ "user_id": { "type": ["string", "integer"] },++ "metadata": { "type": "object" }++ }++}nnew file mode 100644@@@ -0,0 +1,24 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-init.v1.json",++ "title": "MediaUploadInit",++ "description": "The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.",++ "type": "object",++ "required": ["id", "object", "upload"],++ "additionalProperties": true,++ "properties": {++ "id": { "type": "string" },++ "object": { "$ref": "object.v1.json" },++ "upload": {++ "type": "object",++ "required": ["method", "multipart", "complete_url"],++ "additionalProperties": true,++ "properties": {++ "method": { "const": "multipart" },++ "multipart": { "$ref": "upload.v1.json" },++ "complete_url": { "type": "string" },++ "multipart_url": { "type": "string" }++ }++ }++ }++}nnew file mode 100644@@@ -0,0 +1,14 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-part.v1.json",++ "title": "MediaUploadPart",++ "description": "A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.",++ "type": "object",++ "required": ["part_number", "size_bytes", "sha256"],++ "additionalProperties": true,++ "properties": {++ "part_number": { "type": "integer", "minimum": 1 },++ "size_bytes": { "type": "integer", "minimum": 1 },++ "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }++ }++}nnew file mode 100644@@@ -0,0 +1,27 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload.v1.json",++ "title": "MediaUpload",++ "description": "media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.",++ "type": "object",++ "required": ["upload_id", "object_id", "status", "part_size", "total_size", "parts_expected", "expires_at", "created_at"],++ "additionalProperties": true,++ "properties": {++ "upload_id": { "type": "string", "pattern": "^mup_[0-9A-HJKMNP-TV-Z]{26}$" },++ "object_id": { "type": "string", "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$" },++ "status": { "type": "string", "enum": ["active", "completing", "completed", "aborted", "expired"] },++ "part_size": { "type": "integer", "minimum": 5242880 },++ "total_size": { "type": "integer", "minimum": 1 },++ "parts_expected": { "type": "integer", "minimum": 1, "maximum": 10000 },++ "expires_at": { "type": "string", "format": "date-time" },++ "created_at": { "type": "string" },++ "parts": { "type": "array", "items": { "$ref": "upload-part.v1.json" } },++ "received_bytes": { "type": "integer", "minimum": 0 },++ "missing": { "type": "array", "items": { "type": "integer", "minimum": 1 } },++ "token": { "type": "string" },++ "part_url_template": { "type": "string" },++ "status_url": { "type": "string" },++ "complete_url": { "type": "string" },++ "abort_url": { "type": "string" }++ }++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "parts": [++ {}++ ]++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "parts": [++ {++ "part_number": 1,++ "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "kind": "file",++ "size_bytes": 0,++ "multipart": false++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "kind": "file",++ "size_bytes": 8388608,++ "multipart": true,++ "part_size": 8388608,++ "visibility": "private"++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "upload": {++ "method": "multipart"++ }++}nnew file mode 100644@@@ -0,0 +1,66 @@++{++ "id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "object": {++ "id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "media_ref": {++ "media_id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ"++ },++ "legacy_ref": null,++ "app_id": "prj_01K5WZX7S7Q4D2B8N3M6V1C9TA",++ "namespace": "app.prj_01K5WZX7S7Q4D2B8N3M6V1C9TA.avatars",++ "kind": "file",++ "owner": {++ "subject": null,++ "app": "prj_01K5WZX7S7Q4D2B8N3M6V1C9TA",++ "user_id": null++ },++ "visibility": "private",++ "lifecycle_status": "ready",++ "mime_type": "image/png",++ "size_bytes": 48213,++ "content_hash": "3f1c0b8e2a9d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b",++ "metadata": {++ "filename": "a.png"++ },++ "held": false,++ "readiness": {++ "metadata": true,++ "bytes_verified": true,++ "playable": false,++ "reason": "not_playback_kind"++ },++ "public_url": null,++ "created_at": "2026-09-26 08:00:00",++ "updated_at": "2026-09-26 08:00:01",++ "deleted_at": null,++ "locations": [++ {++ "provider": "local",++ "storage_class": "hot",++ "state": "present",++ "size_bytes": 48213,++ "verified_at": "2026-09-26 08:00:01",++ "canonical": true++ }++ ]++ },++ "upload": {++ "method": "multipart",++ "complete_url": "https://openvibe.media/api/v2/demo/objects/med_01K5WZX7S7Q4D2B8N3M6V1C9TZ/complete",++ "multipart": {++ "upload_id": "mup_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "object_id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "status": "active",++ "part_size": 8388608,++ "total_size": 8388608,++ "parts_expected": 1,++ "expires_at": "2026-11-10T00:00:00Z",++ "created_at": "2026-11-09 00:00:00",++ "parts": [],++ "received_bytes": 0,++ "missing": [++ 1++ ]++ }++ }++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "part_number": 0,++ "size_bytes": 0,++ "sha256": "bad"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "part_number": 1,++ "size_bytes": 8388608,++ "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"++}nnew file mode 100644@@@ -0,0 +1,3 @@++{++ "upload_id": "wrong"++}nnew file mode 100644@@@ -0,0 +1,15 @@++{++ "upload_id": "mup_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "object_id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",++ "status": "active",++ "part_size": 8388608,++ "total_size": 8388608,++ "parts_expected": 1,++ "expires_at": "2026-11-10T00:00:00Z",++ "created_at": "2026-11-09 00:00:00",++ "parts": [],++ "received_bytes": 0,++ "missing": [++ 1++ ]++}@@@ -2491,6 +2491,22 @@},"description": "Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'."},++ "routeSchemas": {++ "type": "object",++ "description": "Input and output contract overrides for a route when one capability covers several operations.",++ "additionalProperties": {++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "inputSchema": {++ "type": "string"++ },++ "outputSchema": {++ "type": "string"++ }++ }++ }++ },"sensitive": {"type": "boolean","description": "The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2)."@@@ -4249,6 +4265,296 @@}}},++ "media.upload": {++ "version": "1.0.0",++ "owner": "media",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload.v1.json",++ "title": "MediaUpload",++ "description": "media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.",++ "type": "object",++ "required": [++ "upload_id",++ "object_id",++ "status",++ "part_size",++ "total_size",++ "parts_expected",++ "expires_at",++ "created_at"++ ],++ "additionalProperties": true,++ "properties": {++ "upload_id": {++ "type": "string",++ "pattern": "^mup_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "object_id": {++ "type": "string",++ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "status": {++ "type": "string",++ "enum": [++ "active",++ "completing",++ "completed",++ "aborted",++ "expired"++ ]++ },++ "part_size": {++ "type": "integer",++ "minimum": 5242880++ },++ "total_size": {++ "type": "integer",++ "minimum": 1++ },++ "parts_expected": {++ "type": "integer",++ "minimum": 1,++ "maximum": 10000++ },++ "expires_at": {++ "type": "string",++ "format": "date-time"++ },++ "created_at": {++ "type": "string"++ },++ "parts": {++ "type": "array",++ "items": {++ "$ref": "upload-part.v1.json"++ }++ },++ "received_bytes": {++ "type": "integer",++ "minimum": 0++ },++ "missing": {++ "type": "array",++ "items": {++ "type": "integer",++ "minimum": 1++ }++ },++ "token": {++ "type": "string"++ },++ "part_url_template": {++ "type": "string"++ },++ "status_url": {++ "type": "string"++ },++ "complete_url": {++ "type": "string"++ },++ "abort_url": {++ "type": "string"++ }++ }++ }++ },++ "media.upload-create": {++ "version": "1.0.0",++ "owner": "media",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-create.v1.json",++ "title": "MediaUploadCreate",++ "description": "Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.",++ "type": "object",++ "required": [++ "kind",++ "size_bytes",++ "multipart"++ ],++ "additionalProperties": true,++ "properties": {++ "kind": {++ "type": "string",++ "enum": [++ "vod",++ "clip",++ "file",++ "thumbnail",++ "screenshot",++ "avatar",++ "asset"++ ]++ },++ "size_bytes": {++ "type": "integer",++ "minimum": 1++ },++ "multipart": {++ "const": true++ },++ "part_size": {++ "type": "integer",++ "minimum": 5242880,++ "description": "Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts."++ },++ "visibility": {++ "type": "string",++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ },++ "mime_type": {++ "type": "string"++ },++ "filename": {++ "type": "string"++ },++ "content_hash": {++ "type": "string",++ "pattern": "^[a-fA-F0-9]{64}$"++ },++ "namespace": {++ "type": "string"++ },++ "user_id": {++ "type": [++ "string",++ "integer"++ ]++ },++ "metadata": {++ "type": "object"++ }++ }++ }++ },++ "media.upload-init": {++ "version": "1.0.0",++ "owner": "media",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-init.v1.json",++ "title": "MediaUploadInit",++ "description": "The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.",++ "type": "object",++ "required": [++ "id",++ "object",++ "upload"++ ],++ "additionalProperties": true,++ "properties": {++ "id": {++ "type": "string"++ },++ "object": {++ "$ref": "object.v1.json"++ },++ "upload": {++ "type": "object",++ "required": [++ "method",++ "multipart",++ "complete_url"++ ],++ "additionalProperties": true,++ "properties": {++ "method": {++ "const": "multipart"++ },++ "multipart": {++ "$ref": "upload.v1.json"++ },++ "complete_url": {++ "type": "string"++ },++ "multipart_url": {++ "type": "string"++ }++ }++ }++ }++ }++ },++ "media.upload-part": {++ "version": "1.0.0",++ "owner": "media",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-part.v1.json",++ "title": "MediaUploadPart",++ "description": "A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.",++ "type": "object",++ "required": [++ "part_number",++ "size_bytes",++ "sha256"++ ],++ "additionalProperties": true,++ "properties": {++ "part_number": {++ "type": "integer",++ "minimum": 1++ },++ "size_bytes": {++ "type": "integer",++ "minimum": 1++ },++ "sha256": {++ "type": "string",++ "pattern": "^[a-f0-9]{64}$"++ }++ }++ }++ },++ "media.upload-complete": {++ "version": "1.0.0",++ "owner": "media",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/media/upload-complete.v1.json",++ "title": "MediaUploadComplete",++ "description": "Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.",++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "content_hash": {++ "type": "string",++ "pattern": "^[a-fA-F0-9]{64}$"++ },++ "parts": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "part_number",++ "sha256"++ ],++ "additionalProperties": false,++ "properties": {++ "part_number": {++ "type": "integer",++ "minimum": 1++ },++ "sha256": {++ "type": "string",++ "pattern": "^[a-f0-9]{64}$"++ }++ }++ }++ }++ }++ }++ },"search.index-document": {"version": "1.0.0","owner": "search",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Actor API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bench API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bot API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Chat API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Codes API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Community API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe Connect API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Coupons API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Deals API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Design API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Domains API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Events API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Exchange API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Exchange as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Exchange as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Food API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Games API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Host API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -159,7 +159,7 @@"service": "media","name": "OpenVibe.Media","origin": "https://openvibe.media",-- "operations": 19,++ "operations": 24,"capabilities": 14},{@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Inventory API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Mail API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.MediaHub API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Media API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -662,30 +662,393 @@}}}++ },++ "post": {++ "operationId": "post_api_v2_app_objects",++ "summary": "Upload a file object into an app namespace.",++ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",++ "tags": [++ "media.object"++ ],++ "x-openvibe-capabilities": [++ "media.object.upload"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "media-upload",++ "security": [++ {++ "openvibeToken": [++ "media.object.upload"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.upload-create.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "app",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.upload-init.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },++ "/api/v2/{app}/objects/{id}": {++ "delete": {++ "operationId": "delete_api_v2_app_objects_id",++ "summary": "Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that peri",++ "description": "**media.object.delete** (public): Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that period (checked against the namespace's quotas); refused while the object is under a retention hold. The same verb guards the v1 file delete (DELETE /api/v1/:app/files/:key). media.object.upload also grants it, for tokens issued before the verbs were split, unless the namespace's policy is strict_verbs.",++ "tags": [++ "media.object"++ ],++ "x-openvibe-capabilities": [++ "media.object.delete"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "media-write",++ "security": [++ {++ "openvibeToken": [++ "media.object.delete"++ ]++ }++ ],++ "parameters": [++ {++ "name": "app",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.object.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },++ "/api/v2/{app}/objects/{id}/multipart/{uploadId}": {++ "delete": {++ "operationId": "delete_api_v2_app_objects_id_multipart_uploadId",++ "summary": "Upload a file object into an app namespace.",++ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",++ "tags": [++ "media.object"++ ],++ "x-openvibe-capabilities": [++ "media.object.upload"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "media-upload",++ "security": [++ {++ "openvibeToken": [++ "media.object.upload"++ ]++ }++ ],++ "parameters": [++ {++ "name": "app",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "uploadId",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.upload.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "get": {++ "operationId": "get_api_v2_app_objects_id_multipart_uploadId",++ "summary": "Upload a file object into an app namespace.",++ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",++ "tags": [++ "media.object"++ ],++ "x-openvibe-capabilities": [++ "media.object.upload"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "media-upload",++ "security": [++ {++ "openvibeToken": [++ "media.object.upload"++ ]++ }++ ],++ "parameters": [++ {++ "name": "app",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "uploadId",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.upload.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },++ "/api/v2/{app}/objects/{id}/multipart/{uploadId}/complete": {++ "post": {++ "operationId": "post_api_v2_app_objects_id_multipart_uploadId_complete",++ "summary": "Upload a file object into an app namespace.",++ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",++ "tags": [++ "media.object"++ ],++ "x-openvibe-capabilities": [++ "media.object.upload"++ ],++ "x-openvibe-visibility": [++ "public"++ ],++ "x-openvibe-quota-class": "media-upload",++ "security": [++ {++ "openvibeToken": [++ "media.object.upload"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.upload-complete.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "app",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "id",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "uploadId",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/media.object.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }}},-- "/api/v2/{app}/objects/{id}": {-- "delete": {-- "operationId": "delete_api_v2_app_objects_id",-- "summary": "Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that peri",-- "description": "**media.object.delete** (public): Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that period (checked against the namespace's quotas); refused while the object is under a retention hold. The same verb guards the v1 file delete (DELETE /api/v1/:app/files/:key). media.object.upload also grants it, for tokens issued before the verbs were split, unless the namespace's policy is strict_verbs.",++ "/api/v2/{app}/objects/{id}/multipart/{uploadId}/parts/{n}": {++ "put": {++ "operationId": "put_api_v2_app_objects_id_multipart_uploadId_parts_n",++ "summary": "Upload a file object into an app namespace.",++ "description": "**media.object.upload** (public): Upload a file object into an app namespace.","tags": ["media.object"],"x-openvibe-capabilities": [-- "media.object.delete"++ "media.object.upload"],"x-openvibe-visibility": ["public"],-- "x-openvibe-quota-class": "media-write",++ "x-openvibe-quota-class": "media-upload","security": [{"openvibeToken": [-- "media.object.delete"++ "media.object.upload"]}],++ "requestBody": {++ "required": false,++ "content": {++ "application/octet-stream": {++ "schema": {++ "type": "string",++ "contentEncoding": "binary"++ }++ }++ }++ },"parameters": [{"name": "app",@@@ -702,6 +1065,22 @@"schema": {"type": "string"}++ },++ {++ "name": "uploadId",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "n",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }}],"responses": {@@@ -710,7 +1089,7 @@"content": {"application/json": {"schema": {-- "$ref": "#/components/schemas/media.object.v1"++ "$ref": "#/components/schemas/media.upload-part.v1"}}}@@@ -2688,6 +3067,261 @@}}},++ "media.upload-complete.v1": {++ "title": "MediaUploadComplete",++ "description": "Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.",++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "content_hash": {++ "type": "string",++ "pattern": "^[a-fA-F0-9]{64}$"++ },++ "parts": {++ "type": "array",++ "items": {++ "type": "object",++ "required": [++ "part_number",++ "sha256"++ ],++ "additionalProperties": false,++ "properties": {++ "part_number": {++ "type": "integer",++ "minimum": 1++ },++ "sha256": {++ "type": "string",++ "pattern": "^[a-f0-9]{64}$"++ }++ }++ }++ }++ }++ },++ "media.upload-create.v1": {++ "title": "MediaUploadCreate",++ "description": "Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.",++ "type": "object",++ "required": [++ "kind",++ "size_bytes",++ "multipart"++ ],++ "additionalProperties": true,++ "properties": {++ "kind": {++ "type": "string",++ "enum": [++ "vod",++ "clip",++ "file",++ "thumbnail",++ "screenshot",++ "avatar",++ "asset"++ ]++ },++ "size_bytes": {++ "type": "integer",++ "minimum": 1++ },++ "multipart": {++ "const": true++ },++ "part_size": {++ "type": "integer",++ "minimum": 5242880,++ "description": "Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts."++ },++ "visibility": {++ "type": "string",++ "enum": [++ "public",++ "unlisted",++ "private"++ ]++ },++ "mime_type": {++ "type": "string"++ },++ "filename": {++ "type": "string"++ },++ "content_hash": {++ "type": "string",++ "pattern": "^[a-fA-F0-9]{64}$"++ },++ "namespace": {++ "type": "string"++ },++ "user_id": {++ "type": [++ "string",++ "integer"++ ]++ },++ "metadata": {++ "type": "object"++ }++ }++ },++ "media.upload-init.v1": {++ "title": "MediaUploadInit",++ "description": "The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.",++ "type": "object",++ "required": [++ "id",++ "object",++ "upload"++ ],++ "additionalProperties": true,++ "properties": {++ "id": {++ "type": "string"++ },++ "object": {++ "$ref": "#/components/schemas/media.object.v1"++ },++ "upload": {++ "type": "object",++ "required": [++ "method",++ "multipart",++ "complete_url"++ ],++ "additionalProperties": true,++ "properties": {++ "method": {++ "const": "multipart"++ },++ "multipart": {++ "$ref": "#/components/schemas/media.upload.v1"++ },++ "complete_url": {++ "type": "string"++ },++ "multipart_url": {++ "type": "string"++ }++ }++ }++ }++ },++ "media.upload-part.v1": {++ "title": "MediaUploadPart",++ "description": "A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.",++ "type": "object",++ "required": [++ "part_number",++ "size_bytes",++ "sha256"++ ],++ "additionalProperties": true,++ "properties": {++ "part_number": {++ "type": "integer",++ "minimum": 1++ },++ "size_bytes": {++ "type": "integer",++ "minimum": 1++ },++ "sha256": {++ "type": "string",++ "pattern": "^[a-f0-9]{64}$"++ }++ }++ },++ "media.upload.v1": {++ "title": "MediaUpload",++ "description": "media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.",++ "type": "object",++ "required": [++ "upload_id",++ "object_id",++ "status",++ "part_size",++ "total_size",++ "parts_expected",++ "expires_at",++ "created_at"++ ],++ "additionalProperties": true,++ "properties": {++ "upload_id": {++ "type": "string",++ "pattern": "^mup_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "object_id": {++ "type": "string",++ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "status": {++ "type": "string",++ "enum": [++ "active",++ "completing",++ "completed",++ "aborted",++ "expired"++ ]++ },++ "part_size": {++ "type": "integer",++ "minimum": 5242880++ },++ "total_size": {++ "type": "integer",++ "minimum": 1++ },++ "parts_expected": {++ "type": "integer",++ "minimum": 1,++ "maximum": 10000++ },++ "expires_at": {++ "type": "string",++ "format": "date-time"++ },++ "created_at": {++ "type": "string"++ },++ "parts": {++ "type": "array",++ "items": {++ "$ref": "#/components/schemas/media.upload-part.v1"++ }++ },++ "received_bytes": {++ "type": "integer",++ "minimum": 0++ },++ "missing": {++ "type": "array",++ "items": {++ "type": "integer",++ "minimum": 1++ }++ },++ "token": {++ "type": "string"++ },++ "part_url_template": {++ "type": "string"++ },++ "status_url": {++ "type": "string"++ },++ "complete_url": {++ "type": "string"++ },++ "abort_url": {++ "type": "string"++ }++ }++ },"zone.object-zone.v1": {"title": "ObjectZone","description": "zone.object-zone@1 (ADR-031 amendment 2026-10-02): one named object zone, as OpenVibe.Zone's control API returns it (GET /api/v1/zones/{zone_id}, the list under /api/v1/projects/{project_id}/zones, and the 201 of a create). Zone owns this record: its name, environment, state, access policy and per-zone quota setting. Media owns everything inside it: the objects (ordinary med_ objects in the namespace media_namespace), their keys, bytes and replicas, quota enforcement, usage counting and the one deletion path. Zone never lists keys or holds bytes. The S3 bucket name is `name`, resolved within the project and environment of the access key that signs the request, at https://s3.openvibe.media/<name>/<key>. `ovrn` is ovrn:zone:<project_id>:object-zone/<id>, with the same project_id and id as this record. The id is never reused, and neither is a name: within one project environment a name belongs to one zone for ever, deleted or not, so a signed request names exactly one zone id. Name and env are immutable. Every environment has exactly one `default` zone, whose media_namespace is the environment root. Zone creates it with the environment, and it cannot be deleted on its own. Its access is per-object, and every other zone's is private. JSON Schema cannot compare fields: contracts.zones.checkObjectZone also requires that ovrn names this project_id and id, and that media_namespace is the environment root of project_id and env, followed by .<id> unless the zone is the default. More fields may be added.",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Network API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.News API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenRestream API",-- "version": "0.358.0",-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Play API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Quest API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Report API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Reviews API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Run API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Search API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Services API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Sources API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Space API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tips API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Today API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tools API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Trade API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.VIP API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Vision API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Watch API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Wiki API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Work API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Zone API",-- "version": "0.358.0",-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.359.0",++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -4849,6 +4849,17 @@ export interface Capability {* Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'.*/implementedBy?: string[];++ /**++ * Input and output contract overrides for a route when one capability covers several operations.++ */++ routeSchemas?: {++ [k: string]:++ | {++ inputSchema?: string;++ outputSchema?: string;++ }++ | undefined;++ };/*** The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2).*/@@@ -6688,6 +6699,92 @@ export interface MediaFileUpload {[k: string]: unknown | undefined;}++/** [email protected] (owner: media) */++/**++ * media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.++ */++export interface MediaUpload {++ upload_id: string;++ object_id: string;++ status: "active" | "completing" | "completed" | "aborted" | "expired";++ part_size: number;++ total_size: number;++ parts_expected: number;++ expires_at: string;++ created_at: string;++ parts?: MediaUploadPart[];++ received_bytes?: number;++ missing?: number[];++ token?: string;++ part_url_template?: string;++ status_url?: string;++ complete_url?: string;++ abort_url?: string;++ [k: string]: unknown | undefined;++}++++/** [email protected] (owner: media) */++/**++ * Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.++ */++export interface MediaUploadCreate {++ kind: "vod" | "clip" | "file" | "thumbnail" | "screenshot" | "avatar" | "asset";++ size_bytes: number;++ multipart: true;++ /**++ * Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts.++ */++ part_size?: number;++ visibility?: "public" | "unlisted" | "private";++ mime_type?: string;++ filename?: string;++ content_hash?: string;++ namespace?: string;++ user_id?: string | number;++ metadata?: {};++ [k: string]: unknown | undefined;++}++++/** [email protected] (owner: media) */++/**++ * The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.++ */++export interface MediaUploadInit {++ id: string;++ object: MediaObject;++ upload: {++ method: "multipart";++ multipart: MediaUpload;++ complete_url: string;++ multipart_url?: string;++ [k: string]: unknown | undefined;++ };++ [k: string]: unknown | undefined;++}++++/** [email protected] (owner: media) */++/**++ * A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.++ */++export interface MediaUploadPart {++ part_number: number;++ size_bytes: number;++ sha256: string;++ [k: string]: unknown | undefined;++}++++/** [email protected] (owner: media) */++/**++ * Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.++ */++export interface MediaUploadComplete {++ content_hash?: string;++ parts?: {++ part_number: number;++ sha256: string;++ }[];++}++/** [email protected] (owner: search) *//*** What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.@@@ -119,12 +119,15 @@ function buildOpenApi({ catalog, capabilities, services, version } = load()) {for (const route of cap.implementedBy || []) {const m = HTTP_RE.exec(String(route).trim());if (!m) { other.push({ capability: cap.id, binding: route }); continue; }++ // A capability may expose several operations with different bodies and answers.++ const shape = cap.routeSchemas && cap.routeSchemas[route];++ const binding = shape ? { ...cap, ...shape } : cap;const p = m[2].replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, '{$1}').replace(/\/+$/, '') || '/';for (const method of m[1].toLowerCase().split('|')) {const k = `${method} ${p}`;if (!ops.has(k)) ops.set(k, { method, path: p, caps: [], notes: [] });const op = ops.get(k);-- if (!op.caps.includes(cap)) op.caps.push(cap);++ if (!op.caps.some((c) => c.id === cap.id)) op.caps.push(binding);if (m[3]) op.notes.push(m[3]);}}@@@ -18,7 +18,19 @@"media.object.uploaded"],"implementedBy": [-- "POST /api/v1/:app/files"++ "POST /api/v1/:app/files",++ "POST /api/v2/:app/objects",++ "GET /api/v2/:app/objects/:id/multipart/:uploadId",++ "PUT /api/v2/:app/objects/:id/multipart/:uploadId/parts/:n",++ "POST /api/v2/:app/objects/:id/multipart/:uploadId/complete",++ "DELETE /api/v2/:app/objects/:id/multipart/:uploadId"],-- "inputSchema": "media.file-upload@1"++ "inputSchema": "media.file-upload@1",++ "routeSchemas": {++ "POST /api/v2/:app/objects": { "inputSchema": "media.upload-create@1", "outputSchema": "media.upload-init@1" },++ "GET /api/v2/:app/objects/:id/multipart/:uploadId": { "inputSchema": "common.no-body@1", "outputSchema": "media.upload@1" },++ "PUT /api/v2/:app/objects/:id/multipart/:uploadId/parts/:n": { "inputSchema": "common.binary@1", "outputSchema": "media.upload-part@1" },++ "POST /api/v2/:app/objects/:id/multipart/:uploadId/complete": { "inputSchema": "media.upload-complete@1", "outputSchema": "media.object@1" },++ "DELETE /api/v2/:app/objects/:id/multipart/:uploadId": { "inputSchema": "common.no-body@1", "outputSchema": "media.upload@1" }++ }}@@@ -1,12 +1,12 @@{"name": "openvibe-contracts",-- "version": "0.358.0",++ "version": "0.359.0","lockfileVersion": 3,"requires": true,"packages": {"": {"name": "openvibe-contracts",-- "version": "0.358.0",++ "version": "0.359.0","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.358.0",++ "version": "0.359.0","description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.","main": "index.js","types": "generated/typescript/index.d.ts",@@@ -65,8 +65,9 @@ const ROOT = path.join(__dirname, '..');assert.ok(op && op['x-openvibe-capabilities'].includes(cap.id), `${cap.id}: ${method.toUpperCase()} ${p} in ${cap.owner}'s document`);const text = JSON.stringify(op);const key = (ref) => `${ref.replace(/@(\d+)$/, '.v$1')}`;-- if (cap.outputSchema && !['common.binary@1', 'common.no-body@1'].includes(cap.outputSchema)) assert.ok(text.includes(`#/components/schemas/${key(cap.outputSchema)}"`), `${cap.id} ${method} ${p}: output ${cap.outputSchema}`);-- if (cap.inputSchema && !['common.binary@1', 'common.no-body@1'].includes(cap.inputSchema)) assert.ok(text.includes(`#/components/schemas/${key(cap.inputSchema)}"`), `${cap.id} ${method} ${p}: input ${cap.inputSchema}`);++ const shape = { ...cap, ...(cap.routeSchemas && cap.routeSchemas[route]) };++ if (shape.outputSchema && !['common.binary@1', 'common.no-body@1'].includes(shape.outputSchema)) assert.ok(text.includes(`#/components/schemas/${key(shape.outputSchema)}"`), `${cap.id} ${method} ${p}: output ${shape.outputSchema}`);++ if (shape.inputSchema && !['common.binary@1', 'common.no-body@1'].includes(shape.inputSchema)) assert.ok(text.includes(`#/components/schemas/${key(shape.inputSchema)}"`), `${cap.id} ${method} ${p}: input ${shape.inputSchema}`);}}}
@@ -1,5 +1,9 @@
@@ -1,5 +1,9 @@
# Changelog
# Changelog
+## 0.359.0 — 2026-11-09
+
+- Media multipart uploads in contracts and OpenAPI
+
## 0.358.0 — 2026-11-09
## 0.358.0 — 2026-11-09
- Chat view preference (bubbles or room)
- Chat view preference (bubbles or room)
@@ -20,6 +20,7 @@
@@ -20,6 +20,7 @@
"quotaClass": { "type": "string" },
"quotaClass": { "type": "string" },
"events": { "type": "array", "items": { "type": "string" } },
"events": { "type": "array", "items": { "type": "string" } },
"implementedBy": { "type": "array", "items": { "type": "string" }, "description": "Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'." },
"implementedBy": { "type": "array", "items": { "type": "string" }, "description": "Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'." },
+ "routeSchemas": { "type": "object", "description": "Input and output contract overrides for a route when one capability covers several operations.", "additionalProperties": { "type": "object", "additionalProperties": false, "properties": { "inputSchema": { "type": "string" }, "outputSchema": { "type": "string" } } } },
"sensitive": { "type": "boolean", "description": "The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2)." }
"sensitive": { "type": "boolean", "description": "The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2)." }
}
}
}
}
@@ -365,6 +365,51 @@
@@ -365,6 +365,51 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "media.upload",
+ "version": "1.0.0",
+ "owner": "media",
+ "schema": "media/upload.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "media.upload-create",
+ "version": "1.0.0",
+ "owner": "media",
+ "schema": "media/upload-create.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "media.upload-init",
+ "version": "1.0.0",
+ "owner": "media",
+ "schema": "media/upload-init.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "media.upload-part",
+ "version": "1.0.0",
+ "owner": "media",
+ "schema": "media/upload-part.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "media.upload-complete",
+ "version": "1.0.0",
+ "owner": "media",
+ "schema": "media/upload-complete.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "search.index-document",
"id": "search.index-document",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-complete.v1.json",
+ "title": "MediaUploadComplete",
+ "description": "Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "content_hash": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" },
+ "parts": { "type": "array", "items": { "type": "object", "required": ["part_number", "sha256"], "additionalProperties": false, "properties": { "part_number": { "type": "integer", "minimum": 1 }, "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" } } } }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-create.v1.json",
+ "title": "MediaUploadCreate",
+ "description": "Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.",
+ "type": "object",
+ "required": ["kind", "size_bytes", "multipart"],
+ "additionalProperties": true,
+ "properties": {
+ "kind": { "type": "string", "enum": ["vod", "clip", "file", "thumbnail", "screenshot", "avatar", "asset"] },
+ "size_bytes": { "type": "integer", "minimum": 1 },
+ "multipart": { "const": true },
+ "part_size": { "type": "integer", "minimum": 5242880, "description": "Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts." },
+ "visibility": { "type": "string", "enum": ["public", "unlisted", "private"] },
+ "mime_type": { "type": "string" },
+ "filename": { "type": "string" },
+ "content_hash": { "type": "string", "pattern": "^[a-fA-F0-9]{64}$" },
+ "namespace": { "type": "string" },
+ "user_id": { "type": ["string", "integer"] },
+ "metadata": { "type": "object" }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-init.v1.json",
+ "title": "MediaUploadInit",
+ "description": "The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.",
+ "type": "object",
+ "required": ["id", "object", "upload"],
+ "additionalProperties": true,
+ "properties": {
+ "id": { "type": "string" },
+ "object": { "$ref": "object.v1.json" },
+ "upload": {
+ "type": "object",
+ "required": ["method", "multipart", "complete_url"],
+ "additionalProperties": true,
+ "properties": {
+ "method": { "const": "multipart" },
+ "multipart": { "$ref": "upload.v1.json" },
+ "complete_url": { "type": "string" },
+ "multipart_url": { "type": "string" }
+ }
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-part.v1.json",
+ "title": "MediaUploadPart",
+ "description": "A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.",
+ "type": "object",
+ "required": ["part_number", "size_bytes", "sha256"],
+ "additionalProperties": true,
+ "properties": {
+ "part_number": { "type": "integer", "minimum": 1 },
+ "size_bytes": { "type": "integer", "minimum": 1 },
+ "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload.v1.json",
+ "title": "MediaUpload",
+ "description": "media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.",
+ "type": "object",
+ "required": ["upload_id", "object_id", "status", "part_size", "total_size", "parts_expected", "expires_at", "created_at"],
+ "additionalProperties": true,
+ "properties": {
+ "upload_id": { "type": "string", "pattern": "^mup_[0-9A-HJKMNP-TV-Z]{26}$" },
+ "object_id": { "type": "string", "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$" },
+ "status": { "type": "string", "enum": ["active", "completing", "completed", "aborted", "expired"] },
+ "part_size": { "type": "integer", "minimum": 5242880 },
+ "total_size": { "type": "integer", "minimum": 1 },
+ "parts_expected": { "type": "integer", "minimum": 1, "maximum": 10000 },
+ "expires_at": { "type": "string", "format": "date-time" },
+ "created_at": { "type": "string" },
+ "parts": { "type": "array", "items": { "$ref": "upload-part.v1.json" } },
+ "received_bytes": { "type": "integer", "minimum": 0 },
+ "missing": { "type": "array", "items": { "type": "integer", "minimum": 1 } },
+ "token": { "type": "string" },
+ "part_url_template": { "type": "string" },
+ "status_url": { "type": "string" },
+ "complete_url": { "type": "string" },
+ "abort_url": { "type": "string" }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "parts": [
+ {}
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "parts": [
+ {
+ "part_number": 1,
+ "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "kind": "file",
+ "size_bytes": 0,
+ "multipart": false
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "kind": "file",
+ "size_bytes": 8388608,
+ "multipart": true,
+ "part_size": 8388608,
+ "visibility": "private"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "upload": {
+ "method": "multipart"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
+{
+ "id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "object": {
+ "id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "media_ref": {
+ "media_id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ"
+ },
+ "legacy_ref": null,
+ "app_id": "prj_01K5WZX7S7Q4D2B8N3M6V1C9TA",
+ "namespace": "app.prj_01K5WZX7S7Q4D2B8N3M6V1C9TA.avatars",
+ "kind": "file",
+ "owner": {
+ "subject": null,
+ "app": "prj_01K5WZX7S7Q4D2B8N3M6V1C9TA",
+ "user_id": null
+ },
+ "visibility": "private",
+ "lifecycle_status": "ready",
+ "mime_type": "image/png",
+ "size_bytes": 48213,
+ "content_hash": "3f1c0b8e2a9d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b",
+ "metadata": {
+ "filename": "a.png"
+ },
+ "held": false,
+ "readiness": {
+ "metadata": true,
+ "bytes_verified": true,
+ "playable": false,
+ "reason": "not_playback_kind"
+ },
+ "public_url": null,
+ "created_at": "2026-09-26 08:00:00",
+ "updated_at": "2026-09-26 08:00:01",
+ "deleted_at": null,
+ "locations": [
+ {
+ "provider": "local",
+ "storage_class": "hot",
+ "state": "present",
+ "size_bytes": 48213,
+ "verified_at": "2026-09-26 08:00:01",
+ "canonical": true
+ }
+ ]
+ },
+ "upload": {
+ "method": "multipart",
+ "complete_url": "https://openvibe.media/api/v2/demo/objects/med_01K5WZX7S7Q4D2B8N3M6V1C9TZ/complete",
+ "multipart": {
+ "upload_id": "mup_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "object_id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "status": "active",
+ "part_size": 8388608,
+ "total_size": 8388608,
+ "parts_expected": 1,
+ "expires_at": "2026-11-10T00:00:00Z",
+ "created_at": "2026-11-09 00:00:00",
+ "parts": [],
+ "received_bytes": 0,
+ "missing": [
+ 1
+ ]
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "part_number": 0,
+ "size_bytes": 0,
+ "sha256": "bad"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "part_number": 1,
+ "size_bytes": 8388608,
+ "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
+{
+ "upload_id": "wrong"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
+{
+ "upload_id": "mup_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "object_id": "med_01K5WZX7S7Q4D2B8N3M6V1C9TZ",
+ "status": "active",
+ "part_size": 8388608,
+ "total_size": 8388608,
+ "parts_expected": 1,
+ "expires_at": "2026-11-10T00:00:00Z",
+ "created_at": "2026-11-09 00:00:00",
+ "parts": [],
+ "received_bytes": 0,
+ "missing": [
+ 1
+ ]
+}
@@ -2491,6 +2491,22 @@
@@ -2491,6 +2491,22 @@
},
},
"description": "Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'."
"description": "Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'."
},
},
+ "routeSchemas": {
+ "type": "object",
+ "description": "Input and output contract overrides for a route when one capability covers several operations.",
+ "additionalProperties": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "inputSchema": {
+ "type": "string"
+ },
+ "outputSchema": {
+ "type": "string"
+ }
+ }
+ }
+ },
"sensitive": {
"sensitive": {
"type": "boolean",
"type": "boolean",
"description": "The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2)."
"description": "The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2)."
@@ -4249,6 +4265,296 @@
@@ -4249,6 +4265,296 @@
}
}
}
}
},
},
+ "media.upload": {
+ "version": "1.0.0",
+ "owner": "media",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload.v1.json",
+ "title": "MediaUpload",
+ "description": "media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.",
+ "type": "object",
+ "required": [
+ "upload_id",
+ "object_id",
+ "status",
+ "part_size",
+ "total_size",
+ "parts_expected",
+ "expires_at",
+ "created_at"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "upload_id": {
+ "type": "string",
+ "pattern": "^mup_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "object_id": {
+ "type": "string",
+ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "active",
+ "completing",
+ "completed",
+ "aborted",
+ "expired"
+ ]
+ },
+ "part_size": {
+ "type": "integer",
+ "minimum": 5242880
+ },
+ "total_size": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "parts_expected": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 10000
+ },
+ "expires_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "$ref": "upload-part.v1.json"
+ }
+ },
+ "received_bytes": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "missing": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "minimum": 1
+ }
+ },
+ "token": {
+ "type": "string"
+ },
+ "part_url_template": {
+ "type": "string"
+ },
+ "status_url": {
+ "type": "string"
+ },
+ "complete_url": {
+ "type": "string"
+ },
+ "abort_url": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "media.upload-create": {
+ "version": "1.0.0",
+ "owner": "media",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-create.v1.json",
+ "title": "MediaUploadCreate",
+ "description": "Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.",
+ "type": "object",
+ "required": [
+ "kind",
+ "size_bytes",
+ "multipart"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "enum": [
+ "vod",
+ "clip",
+ "file",
+ "thumbnail",
+ "screenshot",
+ "avatar",
+ "asset"
+ ]
+ },
+ "size_bytes": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "multipart": {
+ "const": true
+ },
+ "part_size": {
+ "type": "integer",
+ "minimum": 5242880,
+ "description": "Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ },
+ "mime_type": {
+ "type": "string"
+ },
+ "filename": {
+ "type": "string"
+ },
+ "content_hash": {
+ "type": "string",
+ "pattern": "^[a-fA-F0-9]{64}$"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "user_id": {
+ "type": [
+ "string",
+ "integer"
+ ]
+ },
+ "metadata": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "media.upload-init": {
+ "version": "1.0.0",
+ "owner": "media",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-init.v1.json",
+ "title": "MediaUploadInit",
+ "description": "The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.",
+ "type": "object",
+ "required": [
+ "id",
+ "object",
+ "upload"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "object": {
+ "$ref": "object.v1.json"
+ },
+ "upload": {
+ "type": "object",
+ "required": [
+ "method",
+ "multipart",
+ "complete_url"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "method": {
+ "const": "multipart"
+ },
+ "multipart": {
+ "$ref": "upload.v1.json"
+ },
+ "complete_url": {
+ "type": "string"
+ },
+ "multipart_url": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "media.upload-part": {
+ "version": "1.0.0",
+ "owner": "media",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-part.v1.json",
+ "title": "MediaUploadPart",
+ "description": "A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.",
+ "type": "object",
+ "required": [
+ "part_number",
+ "size_bytes",
+ "sha256"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "part_number": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "size_bytes": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "sha256": {
+ "type": "string",
+ "pattern": "^[a-f0-9]{64}$"
+ }
+ }
+ }
+ },
+ "media.upload-complete": {
+ "version": "1.0.0",
+ "owner": "media",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/media/upload-complete.v1.json",
+ "title": "MediaUploadComplete",
+ "description": "Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "content_hash": {
+ "type": "string",
+ "pattern": "^[a-fA-F0-9]{64}$"
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "part_number",
+ "sha256"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "part_number": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "sha256": {
+ "type": "string",
+ "pattern": "^[a-f0-9]{64}$"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"search.index-document": {
"search.index-document": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "search",
"owner": "search",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Actor API",
"title": "OpenVibe.Actor API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bench API",
"title": "OpenVibe.Bench API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"title": "OpenVibe.Billing API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"title": "OpenVibe.Blog API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bot API",
"title": "OpenVibe.Bot API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Chat API",
"title": "OpenVibe.Chat API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Codes API",
"title": "OpenVibe.Codes API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Community API",
"title": "OpenVibe.Community API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe Connect API",
"title": "OpenVibe Connect API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Coupons API",
"title": "OpenVibe.Coupons API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Deals API",
"title": "OpenVibe.Deals API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Design API",
"title": "OpenVibe.Design API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Domains API",
"title": "OpenVibe.Domains API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Events API",
"title": "OpenVibe.Events API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Exchange API",
"title": "OpenVibe.Exchange API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Exchange as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Exchange as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Food API",
"title": "OpenVibe.Food API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Games API",
"title": "OpenVibe.Games API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Host API",
"title": "OpenVibe.Host API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -159,7 +159,7 @@
@@ -159,7 +159,7 @@
"service": "media",
"service": "media",
"name": "OpenVibe.Media",
"name": "OpenVibe.Media",
"origin": "https://openvibe.media",
"origin": "https://openvibe.media",
- "operations": 19,
+ "operations": 24,
"capabilities": 14
"capabilities": 14
},
},
{
{
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Inventory API",
"title": "OpenVibe.Inventory API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"title": "OpenVibe.Live API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Mail API",
"title": "OpenVibe.Mail API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.MediaHub API",
"title": "OpenVibe.MediaHub API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Media API",
"title": "OpenVibe.Media API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -662,30 +662,393 @@
@@ -662,30 +662,393 @@
}
}
}
}
}
}
+ },
+ "post": {
+ "operationId": "post_api_v2_app_objects",
+ "summary": "Upload a file object into an app namespace.",
+ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",
+ "tags": [
+ "media.object"
+ ],
+ "x-openvibe-capabilities": [
+ "media.object.upload"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "media-upload",
+ "security": [
+ {
+ "openvibeToken": [
+ "media.object.upload"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.upload-create.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "app",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.upload-init.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v2/{app}/objects/{id}": {
+ "delete": {
+ "operationId": "delete_api_v2_app_objects_id",
+ "summary": "Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that peri",
+ "description": "**media.object.delete** (public): Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that period (checked against the namespace's quotas); refused while the object is under a retention hold. The same verb guards the v1 file delete (DELETE /api/v1/:app/files/:key). media.object.upload also grants it, for tokens issued before the verbs were split, unless the namespace's policy is strict_verbs.",
+ "tags": [
+ "media.object"
+ ],
+ "x-openvibe-capabilities": [
+ "media.object.delete"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "media-write",
+ "security": [
+ {
+ "openvibeToken": [
+ "media.object.delete"
+ ]
+ }
+ ],
+ "parameters": [
+ {
+ "name": "app",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.object.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v2/{app}/objects/{id}/multipart/{uploadId}": {
+ "delete": {
+ "operationId": "delete_api_v2_app_objects_id_multipart_uploadId",
+ "summary": "Upload a file object into an app namespace.",
+ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",
+ "tags": [
+ "media.object"
+ ],
+ "x-openvibe-capabilities": [
+ "media.object.upload"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "media-upload",
+ "security": [
+ {
+ "openvibeToken": [
+ "media.object.upload"
+ ]
+ }
+ ],
+ "parameters": [
+ {
+ "name": "app",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "uploadId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.upload.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "get": {
+ "operationId": "get_api_v2_app_objects_id_multipart_uploadId",
+ "summary": "Upload a file object into an app namespace.",
+ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",
+ "tags": [
+ "media.object"
+ ],
+ "x-openvibe-capabilities": [
+ "media.object.upload"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "media-upload",
+ "security": [
+ {
+ "openvibeToken": [
+ "media.object.upload"
+ ]
+ }
+ ],
+ "parameters": [
+ {
+ "name": "app",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "uploadId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.upload.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/v2/{app}/objects/{id}/multipart/{uploadId}/complete": {
+ "post": {
+ "operationId": "post_api_v2_app_objects_id_multipart_uploadId_complete",
+ "summary": "Upload a file object into an app namespace.",
+ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",
+ "tags": [
+ "media.object"
+ ],
+ "x-openvibe-capabilities": [
+ "media.object.upload"
+ ],
+ "x-openvibe-visibility": [
+ "public"
+ ],
+ "x-openvibe-quota-class": "media-upload",
+ "security": [
+ {
+ "openvibeToken": [
+ "media.object.upload"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.upload-complete.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "app",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "uploadId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/media.object.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
}
}
},
},
- "/api/v2/{app}/objects/{id}": {
- "delete": {
- "operationId": "delete_api_v2_app_objects_id",
- "summary": "Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that peri",
- "description": "**media.object.delete** (public): Delete an object in a namespace (the delete verb of Media's namespace grants, WS-G task 2): a soft delete that keeps the bytes for the retention period, and the restore that undoes it within that period (checked against the namespace's quotas); refused while the object is under a retention hold. The same verb guards the v1 file delete (DELETE /api/v1/:app/files/:key). media.object.upload also grants it, for tokens issued before the verbs were split, unless the namespace's policy is strict_verbs.",
+ "/api/v2/{app}/objects/{id}/multipart/{uploadId}/parts/{n}": {
+ "put": {
+ "operationId": "put_api_v2_app_objects_id_multipart_uploadId_parts_n",
+ "summary": "Upload a file object into an app namespace.",
+ "description": "**media.object.upload** (public): Upload a file object into an app namespace.",
"tags": [
"tags": [
"media.object"
"media.object"
],
],
"x-openvibe-capabilities": [
"x-openvibe-capabilities": [
- "media.object.delete"
+ "media.object.upload"
],
],
"x-openvibe-visibility": [
"x-openvibe-visibility": [
"public"
"public"
],
],
- "x-openvibe-quota-class": "media-write",
+ "x-openvibe-quota-class": "media-upload",
"security": [
"security": [
{
{
"openvibeToken": [
"openvibeToken": [
- "media.object.delete"
+ "media.object.upload"
]
]
}
}
],
],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/octet-stream": {
+ "schema": {
+ "type": "string",
+ "contentEncoding": "binary"
+ }
+ }
+ }
+ },
"parameters": [
"parameters": [
{
{
"name": "app",
"name": "app",
@@ -702,6 +1065,22 @@
@@ -702,6 +1065,22 @@
"schema": {
"schema": {
"type": "string"
"type": "string"
}
}
+ },
+ {
+ "name": "uploadId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "n",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
}
}
],
],
"responses": {
"responses": {
@@ -710,7 +1089,7 @@
@@ -710,7 +1089,7 @@
"content": {
"content": {
"application/json": {
"application/json": {
"schema": {
"schema": {
- "$ref": "#/components/schemas/media.object.v1"
+ "$ref": "#/components/schemas/media.upload-part.v1"
}
}
}
}
}
}
@@ -2688,6 +3067,261 @@
@@ -2688,6 +3067,261 @@
}
}
}
}
},
},
+ "media.upload-complete.v1": {
+ "title": "MediaUploadComplete",
+ "description": "Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "content_hash": {
+ "type": "string",
+ "pattern": "^[a-fA-F0-9]{64}$"
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "part_number",
+ "sha256"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "part_number": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "sha256": {
+ "type": "string",
+ "pattern": "^[a-f0-9]{64}$"
+ }
+ }
+ }
+ }
+ }
+ },
+ "media.upload-create.v1": {
+ "title": "MediaUploadCreate",
+ "description": "Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.",
+ "type": "object",
+ "required": [
+ "kind",
+ "size_bytes",
+ "multipart"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "enum": [
+ "vod",
+ "clip",
+ "file",
+ "thumbnail",
+ "screenshot",
+ "avatar",
+ "asset"
+ ]
+ },
+ "size_bytes": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "multipart": {
+ "const": true
+ },
+ "part_size": {
+ "type": "integer",
+ "minimum": 5242880,
+ "description": "Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts."
+ },
+ "visibility": {
+ "type": "string",
+ "enum": [
+ "public",
+ "unlisted",
+ "private"
+ ]
+ },
+ "mime_type": {
+ "type": "string"
+ },
+ "filename": {
+ "type": "string"
+ },
+ "content_hash": {
+ "type": "string",
+ "pattern": "^[a-fA-F0-9]{64}$"
+ },
+ "namespace": {
+ "type": "string"
+ },
+ "user_id": {
+ "type": [
+ "string",
+ "integer"
+ ]
+ },
+ "metadata": {
+ "type": "object"
+ }
+ }
+ },
+ "media.upload-init.v1": {
+ "title": "MediaUploadInit",
+ "description": "The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.",
+ "type": "object",
+ "required": [
+ "id",
+ "object",
+ "upload"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "object": {
+ "$ref": "#/components/schemas/media.object.v1"
+ },
+ "upload": {
+ "type": "object",
+ "required": [
+ "method",
+ "multipart",
+ "complete_url"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "method": {
+ "const": "multipart"
+ },
+ "multipart": {
+ "$ref": "#/components/schemas/media.upload.v1"
+ },
+ "complete_url": {
+ "type": "string"
+ },
+ "multipart_url": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "media.upload-part.v1": {
+ "title": "MediaUploadPart",
+ "description": "A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.",
+ "type": "object",
+ "required": [
+ "part_number",
+ "size_bytes",
+ "sha256"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "part_number": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "size_bytes": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "sha256": {
+ "type": "string",
+ "pattern": "^[a-f0-9]{64}$"
+ }
+ }
+ },
+ "media.upload.v1": {
+ "title": "MediaUpload",
+ "description": "media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.",
+ "type": "object",
+ "required": [
+ "upload_id",
+ "object_id",
+ "status",
+ "part_size",
+ "total_size",
+ "parts_expected",
+ "expires_at",
+ "created_at"
+ ],
+ "additionalProperties": true,
+ "properties": {
+ "upload_id": {
+ "type": "string",
+ "pattern": "^mup_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "object_id": {
+ "type": "string",
+ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "active",
+ "completing",
+ "completed",
+ "aborted",
+ "expired"
+ ]
+ },
+ "part_size": {
+ "type": "integer",
+ "minimum": 5242880
+ },
+ "total_size": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "parts_expected": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 10000
+ },
+ "expires_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "parts": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/media.upload-part.v1"
+ }
+ },
+ "received_bytes": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "missing": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "minimum": 1
+ }
+ },
+ "token": {
+ "type": "string"
+ },
+ "part_url_template": {
+ "type": "string"
+ },
+ "status_url": {
+ "type": "string"
+ },
+ "complete_url": {
+ "type": "string"
+ },
+ "abort_url": {
+ "type": "string"
+ }
+ }
+ },
"zone.object-zone.v1": {
"zone.object-zone.v1": {
"title": "ObjectZone",
"title": "ObjectZone",
"description": "zone.object-zone@1 (ADR-031 amendment 2026-10-02): one named object zone, as OpenVibe.Zone's control API returns it (GET /api/v1/zones/{zone_id}, the list under /api/v1/projects/{project_id}/zones, and the 201 of a create). Zone owns this record: its name, environment, state, access policy and per-zone quota setting. Media owns everything inside it: the objects (ordinary med_ objects in the namespace media_namespace), their keys, bytes and replicas, quota enforcement, usage counting and the one deletion path. Zone never lists keys or holds bytes. The S3 bucket name is `name`, resolved within the project and environment of the access key that signs the request, at https://s3.openvibe.media/<name>/<key>. `ovrn` is ovrn:zone:<project_id>:object-zone/<id>, with the same project_id and id as this record. The id is never reused, and neither is a name: within one project environment a name belongs to one zone for ever, deleted or not, so a signed request names exactly one zone id. Name and env are immutable. Every environment has exactly one `default` zone, whose media_namespace is the environment root. Zone creates it with the environment, and it cannot be deleted on its own. Its access is per-object, and every other zone's is private. JSON Schema cannot compare fields: contracts.zones.checkObjectZone also requires that ovrn names this project_id and id, and that media_namespace is the environment root of project_id and env, followed by .<id> unless the zone is the default. More fields may be added.",
"description": "zone.object-zone@1 (ADR-031 amendment 2026-10-02): one named object zone, as OpenVibe.Zone's control API returns it (GET /api/v1/zones/{zone_id}, the list under /api/v1/projects/{project_id}/zones, and the 201 of a create). Zone owns this record: its name, environment, state, access policy and per-zone quota setting. Media owns everything inside it: the objects (ordinary med_ objects in the namespace media_namespace), their keys, bytes and replicas, quota enforcement, usage counting and the one deletion path. Zone never lists keys or holds bytes. The S3 bucket name is `name`, resolved within the project and environment of the access key that signs the request, at https://s3.openvibe.media/<name>/<key>. `ovrn` is ovrn:zone:<project_id>:object-zone/<id>, with the same project_id and id as this record. The id is never reused, and neither is a name: within one project environment a name belongs to one zone for ever, deleted or not, so a signed request names exactly one zone id. Name and env are immutable. Every environment has exactly one `default` zone, whose media_namespace is the environment root. Zone creates it with the environment, and it cannot be deleted on its own. Its access is per-object, and every other zone's is private. JSON Schema cannot compare fields: contracts.zones.checkObjectZone also requires that ovrn names this project_id and id, and that media_namespace is the environment root of project_id and env, followed by .<id> unless the zone is the default. More fields may be added.",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Network API",
"title": "OpenVibe.Network API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.News API",
"title": "OpenVibe.News API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRestream API",
"title": "OpenRestream API",
- "version": "0.358.0",
- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Play API",
"title": "OpenVibe.Play API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Quest API",
"title": "OpenVibe.Quest API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Report API",
"title": "OpenVibe.Report API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Reviews API",
"title": "OpenVibe.Reviews API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Run API",
"title": "OpenVibe.Run API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Search API",
"title": "OpenVibe.Search API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Services API",
"title": "OpenVibe.Services API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Sources API",
"title": "OpenVibe.Sources API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Space API",
"title": "OpenVibe.Space API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tips API",
"title": "OpenVibe.Tips API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Today API",
"title": "OpenVibe.Today API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tools API",
"title": "OpenVibe.Tools API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Trade API",
"title": "OpenVibe.Trade API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.VIP API",
"title": "OpenVibe.VIP API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Vision API",
"title": "OpenVibe.Vision API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Watch API",
"title": "OpenVibe.Watch API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Wiki API",
"title": "OpenVibe.Wiki API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Work API",
"title": "OpenVibe.Work API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Zone API",
"title": "OpenVibe.Zone API",
- "version": "0.358.0",
- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.358.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.359.0",
+ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.359.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -4849,6 +4849,17 @@ export interface Capability {
@@ -4849,6 +4849,17 @@ export interface Capability {
* Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'.
* Current route(s) that perform this action today, e.g. 'POST /api/v1/:app/files'.
*/
*/
implementedBy?: string[];
implementedBy?: string[];
+ /**
+ * Input and output contract overrides for a route when one capability covers several operations.
+ */
+ routeSchemas?: {
+ [k: string]:
+ | {
+ inputSchema?: string;
+ outputSchema?: string;
+ }
+ | undefined;
+ };
/**
/**
* The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2).
* The action has an external side effect (money, sending as the person, publishing, applying, deleting, physical control): an agent needs its owner's confirmation unless a standing rule covers it (roadmap WS-Z2).
*/
*/
@@ -6688,6 +6699,92 @@ export interface MediaFileUpload {
@@ -6688,6 +6699,92 @@ export interface MediaFileUpload {
[k: string]: unknown | undefined;
[k: string]: unknown | undefined;
}
}
+/** [email protected] (owner: media) */
+/**
+ * media.upload@1: a resumable multipart session. Store upload_id and object_id to resume after a reload; GET status lists received and missing parts. URLs contain a short-lived upload token and should not be logged.
+ */
+export interface MediaUpload {
+ upload_id: string;
+ object_id: string;
+ status: "active" | "completing" | "completed" | "aborted" | "expired";
+ part_size: number;
+ total_size: number;
+ parts_expected: number;
+ expires_at: string;
+ created_at: string;
+ parts?: MediaUploadPart[];
+ received_bytes?: number;
+ missing?: number[];
+ token?: string;
+ part_url_template?: string;
+ status_url?: string;
+ complete_url?: string;
+ abort_url?: string;
+ [k: string]: unknown | undefined;
+}
+
+/** [email protected] (owner: media) */
+/**
+ * Create a Media object with a multipart upload session. The caller needs media.object.upload for the tenant namespace; the upload token then authorizes parts and completion.
+ */
+export interface MediaUploadCreate {
+ kind: "vod" | "clip" | "file" | "thumbnail" | "screenshot" | "avatar" | "asset";
+ size_bytes: number;
+ multipart: true;
+ /**
+ * Use 8388608 for 8 MiB parts; the service may increase it to stay below 10000 parts.
+ */
+ part_size?: number;
+ visibility?: "public" | "unlisted" | "private";
+ mime_type?: string;
+ filename?: string;
+ content_hash?: string;
+ namespace?: string;
+ user_id?: string | number;
+ metadata?: {};
+ [k: string]: unknown | undefined;
+}
+
+/** [email protected] (owner: media) */
+/**
+ * The object and its presigned multipart session after POST /api/v2/:app/objects. Send parts to part_url_template in any order, then complete.
+ */
+export interface MediaUploadInit {
+ id: string;
+ object: MediaObject;
+ upload: {
+ method: "multipart";
+ multipart: MediaUpload;
+ complete_url: string;
+ multipart_url?: string;
+ [k: string]: unknown | undefined;
+ };
+ [k: string]: unknown | undefined;
+}
+
+/** [email protected] (owner: media) */
+/**
+ * A verified part received by Media. PUT the raw bytes to the presigned URL; X-Content-SHA256 is optional.
+ */
+export interface MediaUploadPart {
+ part_number: number;
+ size_bytes: number;
+ sha256: string;
+ [k: string]: unknown | undefined;
+}
+
+/** [email protected] (owner: media) */
+/**
+ * Complete an upload after all parts arrive. Media assembles the bytes, verifies the optional hashes and content type, and returns the ready object.
+ */
+export interface MediaUploadComplete {
+ content_hash?: string;
+ parts?: {
+ part_number: number;
+ sha256: string;
+ }[];
+}
+
/** [email protected] (owner: search) */
/** [email protected] (owner: search) */
/**
/**
* What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.
* What an owning service tells OpenVibe.Search about one of its resources (roadmap §15.12, §4.2 A). The owner stays the source of truth; Search keeps a revision-ordered, permission-aware copy for discovery. A document with deleted=true is a tombstone: it removes the resource from every result and wins over any upsert with the same or an older revision.
@@ -119,12 +119,15 @@ function buildOpenApi({ catalog, capabilities, services, version } = load()) {
@@ -119,12 +119,15 @@ function buildOpenApi({ catalog, capabilities, services, version } = load()) {
for (const route of cap.implementedBy || []) {
for (const route of cap.implementedBy || []) {
const m = HTTP_RE.exec(String(route).trim());
const m = HTTP_RE.exec(String(route).trim());
if (!m) { other.push({ capability: cap.id, binding: route }); continue; }
if (!m) { other.push({ capability: cap.id, binding: route }); continue; }
+ // A capability may expose several operations with different bodies and answers.
+ const shape = cap.routeSchemas && cap.routeSchemas[route];
+ const binding = shape ? { ...cap, ...shape } : cap;
const p = m[2].replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, '{$1}').replace(/\/+$/, '') || '/';
const p = m[2].replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, '{$1}').replace(/\/+$/, '') || '/';
for (const method of m[1].toLowerCase().split('|')) {
for (const method of m[1].toLowerCase().split('|')) {
const k = `${method} ${p}`;
const k = `${method} ${p}`;
if (!ops.has(k)) ops.set(k, { method, path: p, caps: [], notes: [] });
if (!ops.has(k)) ops.set(k, { method, path: p, caps: [], notes: [] });
const op = ops.get(k);
const op = ops.get(k);
- if (!op.caps.includes(cap)) op.caps.push(cap);
+ if (!op.caps.some((c) => c.id === cap.id)) op.caps.push(binding);
if (m[3]) op.notes.push(m[3]);
if (m[3]) op.notes.push(m[3]);
}
}
}
}
@@ -18,7 +18,19 @@
@@ -18,7 +18,19 @@
"media.object.uploaded"
"media.object.uploaded"
],
],
"implementedBy": [
"implementedBy": [
- "POST /api/v1/:app/files"
+ "POST /api/v1/:app/files",
+ "POST /api/v2/:app/objects",
+ "GET /api/v2/:app/objects/:id/multipart/:uploadId",
+ "PUT /api/v2/:app/objects/:id/multipart/:uploadId/parts/:n",
+ "POST /api/v2/:app/objects/:id/multipart/:uploadId/complete",
+ "DELETE /api/v2/:app/objects/:id/multipart/:uploadId"
],
],
- "inputSchema": "media.file-upload@1"
+ "inputSchema": "media.file-upload@1",
+ "routeSchemas": {
+ "POST /api/v2/:app/objects": { "inputSchema": "media.upload-create@1", "outputSchema": "media.upload-init@1" },
+ "GET /api/v2/:app/objects/:id/multipart/:uploadId": { "inputSchema": "common.no-body@1", "outputSchema": "media.upload@1" },
+ "PUT /api/v2/:app/objects/:id/multipart/:uploadId/parts/:n": { "inputSchema": "common.binary@1", "outputSchema": "media.upload-part@1" },
+ "POST /api/v2/:app/objects/:id/multipart/:uploadId/complete": { "inputSchema": "media.upload-complete@1", "outputSchema": "media.object@1" },
+ "DELETE /api/v2/:app/objects/:id/multipart/:uploadId": { "inputSchema": "common.no-body@1", "outputSchema": "media.upload@1" }
+ }
}
}
@@ -1,12 +1,12 @@
@@ -1,12 +1,12 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.358.0",
+ "version": "0.359.0",
"lockfileVersion": 3,
"lockfileVersion": 3,
"requires": true,
"requires": true,
"packages": {
"packages": {
"": {
"": {
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.358.0",
+ "version": "0.359.0",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.358.0",
+ "version": "0.359.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",
@@ -65,8 +65,9 @@ const ROOT = path.join(__dirname, '..');
@@ -65,8 +65,9 @@ const ROOT = path.join(__dirname, '..');
assert.ok(op && op['x-openvibe-capabilities'].includes(cap.id), `${cap.id}: ${method.toUpperCase()} ${p} in ${cap.owner}'s document`);
assert.ok(op && op['x-openvibe-capabilities'].includes(cap.id), `${cap.id}: ${method.toUpperCase()} ${p} in ${cap.owner}'s document`);
const text = JSON.stringify(op);
const text = JSON.stringify(op);
const key = (ref) => `${ref.replace(/@(\d+)$/, '.v$1')}`;
const key = (ref) => `${ref.replace(/@(\d+)$/, '.v$1')}`;
- if (cap.outputSchema && !['common.binary@1', 'common.no-body@1'].includes(cap.outputSchema)) assert.ok(text.includes(`#/components/schemas/${key(cap.outputSchema)}"`), `${cap.id} ${method} ${p}: output ${cap.outputSchema}`);
- if (cap.inputSchema && !['common.binary@1', 'common.no-body@1'].includes(cap.inputSchema)) assert.ok(text.includes(`#/components/schemas/${key(cap.inputSchema)}"`), `${cap.id} ${method} ${p}: input ${cap.inputSchema}`);
+ const shape = { ...cap, ...(cap.routeSchemas && cap.routeSchemas[route]) };
+ if (shape.outputSchema && !['common.binary@1', 'common.no-body@1'].includes(shape.outputSchema)) assert.ok(text.includes(`#/components/schemas/${key(shape.outputSchema)}"`), `${cap.id} ${method} ${p}: output ${shape.outputSchema}`);
+ if (shape.inputSchema && !['common.binary@1', 'common.no-body@1'].includes(shape.inputSchema)) assert.ok(text.includes(`#/components/schemas/${key(shape.inputSchema)}"`), `${cap.id} ${method} ${p}: input ${shape.inputSchema}`);
}
}
}
}
}
}