openvibers/openvibe.contracts Commits
0.241.0: ai.credential-put@2 and ai.credential@2 — one key per provider (#249)
Changes
@@@ -4,6 +4,20 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) thfrom `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,the notes were in the tag and commit messages (`git tag -n1`).++## 0.241.0 — 2026-10-30++++- **AI: one credential per provider** (Codes C3; research `research-2026-10-30/codes-c3-connections.md` items 1 and 2).++ `ai.credential-put@2` and `ai.credential@2` are additive on `@1`: the provider enum gains `deepseek`, `minimax`,++ `openrouter` and `custom` beside `anthropic`, `openai` and `node`, and a PUT may carry `key` (v1's `api_key` stays++ accepted) and its own `budget_usd_per_day`. `custom` requires an https `base_url`; `node` still takes a machine and no++ key. A person may now keep one key per provider, and the route without a provider still stores the default one.++ `ai.credential@2` returns the same body as `@1` with the widened provider, and `key_hint` for every provider except++ `node`.++- **Tooling:** the registry can hold more than one major of one contract id — the bare id resolves to the newest listed++ and `id@N` to that major — so `ai.credential-put@1` keeps resolving while `@2` is the one callers name. The bundle++ keys a multi-major id as `id@N`, the catalog check looks each entry up by its own major, and a fixture set is checked++ against the newest major of its id. `ai.credential-put@2` is the first contract to use this.++## 0.240.0 — 2026-10-29- **OpenVibe.Vision's API** (plan §5.8b): the service manifest now lists the 20 capabilities its routes serve today —nnew file mode 100644@@@ -0,0 +1,142 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential-put.v2.json",++ "title": "AiCredentialPutV2",++ "description": "ai.credential-put@2 (OpenVibe.AI; Codes C3): one person's own provider key per provider, stored by the service that holds their consent, PUT /api/v1/credentials/{subject}/{provider} with capability ai.credential.manage. It adds the provider dimension to ai.credential-put@1: a person may keep an Anthropic, OpenAI, DeepSeek, MiniMax, OpenRouter or custom key side by side, each with its own daily budget, and the route without a provider still stores the default one. `key` is the secret (v1's `api_key` stays accepted); `base_url` names the endpoint of a custom provider and is optional elsewhere. OpenVibe.AI encrypts the key at rest, bound to its owner, subject and provider, and never returns it. Provider `node` is unchanged: the person's own machine, named by `machine`, with no key.",++ "type": "object",++ "required": [++ "provider"++ ],++ "additionalProperties": false,++ "properties": {++ "provider": {++ "enum": [++ "anthropic",++ "openai",++ "deepseek",++ "minimax",++ "openrouter",++ "custom",++ "node"++ ],++ "description": "anthropic = Anthropic's Messages API; openai = any OpenAI-compatible endpoint; deepseek, minimax and openrouter = those providers; custom = the endpoint in base_url (a URL that speaks the OpenAI or the Anthropic format, by the route it is used on); node = the person's own machine (no key, no base_url, no cost)."++ },++ "key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400,++ "description": "The provider key (ai.credential-put@2's name for v1's api_key). Required the first time, and whenever provider or base_url changes (a key is never sent to a new endpoint without being entered again); otherwise the stored key is kept, and it is never returned."++ },++ "api_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400,++ "description": "The ai.credential-put@1 name for `key`, still accepted. When both are sent, `key` wins."++ },++ "base_url": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$",++ "description": "The endpoint of a custom provider (required for it): https, no credentials, query or fragment. OpenVibe.AI connects only to public addresses."++ },++ "machine": {++ "type": "string",++ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",++ "description": "provider node: the person's own machine (openvibe.bot/machines) whose OpenVibe Node runs the model, or `any` of their own."++ },++ "models": {++ "type": "object",++ "additionalProperties": false,++ "maxProperties": 5,++ "properties": {++ "chat": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "vision": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "director": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "summary": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "legacy": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ }++ },++ "description": "Model per role on this provider; `chat` is the default for the others."++ },++ "budget_usd_per_day": {++ "type": "number",++ "minimum": 0,++ "maximum": 1000,++ "description": "The person's own daily cap on estimated spend with this provider's key; 0 or absent = no cap."++ }++ },++ "allOf": [++ {++ "if": {++ "properties": {++ "provider": {++ "const": "node"++ }++ },++ "required": [++ "provider"++ ]++ },++ "then": {++ "required": [++ "machine"++ ],++ "not": {++ "anyOf": [++ {++ "required": [++ "key"++ ]++ },++ {++ "required": [++ "api_key"++ ]++ },++ {++ "required": [++ "base_url"++ ]++ }++ ]++ }++ }++ },++ {++ "if": {++ "properties": {++ "provider": {++ "const": "custom"++ }++ },++ "required": [++ "provider"++ ]++ },++ "then": {++ "required": [++ "base_url"++ ]++ }++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,136 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential.v2.json",++ "title": "AiCredentialV2",++ "description": "ai.credential@2 (OpenVibe.AI; Codes C3): one stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject} or /{subject}/{provider}): never the key, only its last four characters. It widens ai.credential@1's provider to the providers of ai.credential-put@2, so a person may keep one key per provider; `key_hint` is present for every provider except `node`, whose machine is named instead.",++ "type": "object",++ "required": [++ "subject",++ "owner",++ "provider",++ "created_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{1,31}$",++ "description": "The service that stored it; only it may use or change it."++ },++ "provider": {++ "enum": [++ "anthropic",++ "openai",++ "deepseek",++ "minimax",++ "openrouter",++ "custom",++ "node"++ ]++ },++ "machine": {++ "type": [++ "string",++ "null"++ ],++ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",++ "description": "provider node: the machine it runs on, or `any` of the person's own"++ },++ "base_url": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 300++ },++ "key_hint": {++ "type": "string",++ "pattern": "^…[\\s\\S]{1,4}$"++ },++ "models": {++ "type": "object",++ "additionalProperties": false,++ "maxProperties": 5,++ "properties": {++ "chat": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "vision": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "director": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "summary": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "legacy": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ }++ },++ "description": "Model per role on this provider; `chat` is the default for the others."++ },++ "budget_usd_per_day": {++ "type": [++ "number",++ "null"++ ],++ "minimum": 0++ },++ "spent_usd_today": {++ "type": "number",++ "minimum": 0++ },++ "created_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ },++ "last_used_at": {++ "type": [++ "string",++ "null"++ ],++ "format": "date-time"++ }++ },++ "allOf": [++ {++ "if": {++ "properties": {++ "provider": {++ "not": {++ "const": "node"++ }++ }++ },++ "required": [++ "provider"++ ]++ },++ "then": {++ "required": [++ "key_hint"++ ]++ }++ }++ ]++}@@@ -1306,6 +1306,15 @@"compatibility": "backward","status": "active"},++ {++ "id": "ai.credential-put",++ "version": "2.0.0",++ "owner": "ai",++ "schema": "ai/credential-put.v2.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "ai.credential","version": "1.0.0",@@@ -1315,6 +1324,15 @@"compatibility": "backward","status": "active"},++ {++ "id": "ai.credential",++ "version": "2.0.0",++ "owner": "ai",++ "schema": "ai/credential.v2.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "ai.attribution-quota-put","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"custom","key":"sk-custom-EXAMPLEEXAMPLE","base_url":"http://llm.example.com/anthropic"}nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"custom","key":"sk-custom-EXAMPLEEXAMPLE"}nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"groq","key":"sk-groq-EXAMPLEEXAMPLE"}nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"custom","key":"sk-custom-EXAMPLEEXAMPLEEXAMPLE","base_url":"https://llm.example.com/anthropic","budget_usd_per_day":1}nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"deepseek","key":"sk-deepseek-EXAMPLEEXAMPLEEXAMPLE","models":{"chat":"deepseek-chat"},"budget_usd_per_day":3}nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"minimax","key":"sk-minimax-EXAMPLEEXAMPLEEXAMPLE","models":{"chat":"MiniMax-M2"}}nnew file mode 100644@@@ -0,0 +1 @@++{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"codes","provider":"groq","key_hint":"…MPLE","created_at":"2026-10-30T00:00:00.000Z","updated_at":"2026-10-30T00:00:00.000Z"}nnew file mode 100644@@@ -0,0 +1 @@++{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"codes","provider":"custom","base_url":"https://llm.example.com/anthropic","key_hint":"…MPLE","models":{},"budget_usd_per_day":null,"spent_usd_today":0,"created_at":"2026-10-30T00:00:00.000Z","updated_at":"2026-10-30T00:00:00.000Z","last_used_at":null}nnew file mode 100644@@@ -0,0 +1 @@++{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"codes","provider":"deepseek","base_url":null,"key_hint":"…MPLE","models":{"chat":"deepseek-chat"},"budget_usd_per_day":3,"spent_usd_today":0.02,"created_at":"2026-10-30T00:00:00.000Z","updated_at":"2026-10-30T00:00:00.000Z","last_used_at":null}@@@ -13857,7 +13857,7 @@}}},-- "ai.credential-put": {++ "ai.credential-put@1": {"version": "1.0.0","owner": "ai","status": "active",@@@ -13971,7 +13971,154 @@]}},-- "ai.credential": {++ "ai.credential-put@2": {++ "version": "2.0.0",++ "owner": "ai",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential-put.v2.json",++ "title": "AiCredentialPutV2",++ "description": "ai.credential-put@2 (OpenVibe.AI; Codes C3): one person's own provider key per provider, stored by the service that holds their consent, PUT /api/v1/credentials/{subject}/{provider} with capability ai.credential.manage. It adds the provider dimension to ai.credential-put@1: a person may keep an Anthropic, OpenAI, DeepSeek, MiniMax, OpenRouter or custom key side by side, each with its own daily budget, and the route without a provider still stores the default one. `key` is the secret (v1's `api_key` stays accepted); `base_url` names the endpoint of a custom provider and is optional elsewhere. OpenVibe.AI encrypts the key at rest, bound to its owner, subject and provider, and never returns it. Provider `node` is unchanged: the person's own machine, named by `machine`, with no key.",++ "type": "object",++ "required": [++ "provider"++ ],++ "additionalProperties": false,++ "properties": {++ "provider": {++ "enum": [++ "anthropic",++ "openai",++ "deepseek",++ "minimax",++ "openrouter",++ "custom",++ "node"++ ],++ "description": "anthropic = Anthropic's Messages API; openai = any OpenAI-compatible endpoint; deepseek, minimax and openrouter = those providers; custom = the endpoint in base_url (a URL that speaks the OpenAI or the Anthropic format, by the route it is used on); node = the person's own machine (no key, no base_url, no cost)."++ },++ "key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400,++ "description": "The provider key (ai.credential-put@2's name for v1's api_key). Required the first time, and whenever provider or base_url changes (a key is never sent to a new endpoint without being entered again); otherwise the stored key is kept, and it is never returned."++ },++ "api_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400,++ "description": "The ai.credential-put@1 name for `key`, still accepted. When both are sent, `key` wins."++ },++ "base_url": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$",++ "description": "The endpoint of a custom provider (required for it): https, no credentials, query or fragment. OpenVibe.AI connects only to public addresses."++ },++ "machine": {++ "type": "string",++ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",++ "description": "provider node: the person's own machine (openvibe.bot/machines) whose OpenVibe Node runs the model, or `any` of their own."++ },++ "models": {++ "type": "object",++ "additionalProperties": false,++ "maxProperties": 5,++ "properties": {++ "chat": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "vision": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "director": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "summary": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "legacy": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ }++ },++ "description": "Model per role on this provider; `chat` is the default for the others."++ },++ "budget_usd_per_day": {++ "type": "number",++ "minimum": 0,++ "maximum": 1000,++ "description": "The person's own daily cap on estimated spend with this provider's key; 0 or absent = no cap."++ }++ },++ "allOf": [++ {++ "if": {++ "properties": {++ "provider": {++ "const": "node"++ }++ },++ "required": [++ "provider"++ ]++ },++ "then": {++ "required": [++ "machine"++ ],++ "not": {++ "anyOf": [++ {++ "required": [++ "key"++ ]++ },++ {++ "required": [++ "api_key"++ ]++ },++ {++ "required": [++ "base_url"++ ]++ }++ ]++ }++ }++ },++ {++ "if": {++ "properties": {++ "provider": {++ "const": "custom"++ }++ },++ "required": [++ "provider"++ ]++ },++ "then": {++ "required": [++ "base_url"++ ]++ }++ }++ ]++ }++ },++ "ai.credential@1": {"version": "1.0.0","owner": "ai","status": "active",@@@ -14109,6 +14256,147 @@]}},++ "ai.credential@2": {++ "version": "2.0.0",++ "owner": "ai",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential.v2.json",++ "title": "AiCredentialV2",++ "description": "ai.credential@2 (OpenVibe.AI; Codes C3): one stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject} or /{subject}/{provider}): never the key, only its last four characters. It widens ai.credential@1's provider to the providers of ai.credential-put@2, so a person may keep one key per provider; `key_hint` is present for every provider except `node`, whose machine is named instead.",++ "type": "object",++ "required": [++ "subject",++ "owner",++ "provider",++ "created_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{1,31}$",++ "description": "The service that stored it; only it may use or change it."++ },++ "provider": {++ "enum": [++ "anthropic",++ "openai",++ "deepseek",++ "minimax",++ "openrouter",++ "custom",++ "node"++ ]++ },++ "machine": {++ "type": [++ "string",++ "null"++ ],++ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",++ "description": "provider node: the machine it runs on, or `any` of the person's own"++ },++ "base_url": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 300++ },++ "key_hint": {++ "type": "string",++ "pattern": "^…[\\s\\S]{1,4}$"++ },++ "models": {++ "type": "object",++ "additionalProperties": false,++ "maxProperties": 5,++ "properties": {++ "chat": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "vision": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "director": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "summary": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ },++ "legacy": {++ "type": "string",++ "minLength": 1,++ "maxLength": 120++ }++ },++ "description": "Model per role on this provider; `chat` is the default for the others."++ },++ "budget_usd_per_day": {++ "type": [++ "number",++ "null"++ ],++ "minimum": 0++ },++ "spent_usd_today": {++ "type": "number",++ "minimum": 0++ },++ "created_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ },++ "last_used_at": {++ "type": [++ "string",++ "null"++ ],++ "format": "date-time"++ }++ },++ "allOf": [++ {++ "if": {++ "properties": {++ "provider": {++ "not": {++ "const": "node"++ }++ }++ },++ "required": [++ "provider"++ ]++ },++ "then": {++ "required": [++ "key_hint"++ ]++ }++ }++ ]++ }++ },"ai.attribution-quota-put": {"version": "1.0.0","owner": "ai",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Actor API",-- "version": "0.240.0",-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.Inventory API",-- "version": "0.240.0",-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.Network API",-- "version": "0.240.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.241.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"@@@ -151930,6 +151930,49 @@ export type AiCredentialPut = {budget_usd_per_day?: number;};++/** [email protected] (owner: ai) */++/**++ * ai.credential-put@2 (OpenVibe.AI; Codes C3): one person's own provider key per provider, stored by the service that holds their consent, PUT /api/v1/credentials/{subject}/{provider} with capability ai.credential.manage. It adds the provider dimension to ai.credential-put@1: a person may keep an Anthropic, OpenAI, DeepSeek, MiniMax, OpenRouter or custom key side by side, each with its own daily budget, and the route without a provider still stores the default one. `key` is the secret (v1's `api_key` stays accepted); `base_url` names the endpoint of a custom provider and is optional elsewhere. OpenVibe.AI encrypts the key at rest, bound to its owner, subject and provider, and never returns it. Provider `node` is unchanged: the person's own machine, named by `machine`, with no key.++ */++export type AiCredentialPutV2 = {++ [k: string]: unknown | undefined;++} & {++ /**++ * anthropic = Anthropic's Messages API; openai = any OpenAI-compatible endpoint; deepseek, minimax and openrouter = those providers; custom = the endpoint in base_url (a URL that speaks the OpenAI or the Anthropic format, by the route it is used on); node = the person's own machine (no key, no base_url, no cost).++ */++ provider: "anthropic" | "openai" | "deepseek" | "minimax" | "openrouter" | "custom" | "node";++ /**++ * The provider key (ai.credential-put@2's name for v1's api_key). Required the first time, and whenever provider or base_url changes (a key is never sent to a new endpoint without being entered again); otherwise the stored key is kept, and it is never returned.++ */++ key?: string;++ /**++ * The ai.credential-put@1 name for `key`, still accepted. When both are sent, `key` wins.++ */++ api_key?: string;++ /**++ * The endpoint of a custom provider (required for it): https, no credentials, query or fragment. OpenVibe.AI connects only to public addresses.++ */++ base_url?: string;++ /**++ * provider node: the person's own machine (openvibe.bot/machines) whose OpenVibe Node runs the model, or `any` of their own.++ */++ machine?: string;++ /**++ * Model per role on this provider; `chat` is the default for the others.++ */++ models?: {++ chat?: string;++ vision?: string;++ director?: string;++ summary?: string;++ legacy?: string;++ };++ /**++ * The person's own daily cap on estimated spend with this provider's key; 0 or absent = no cap.++ */++ budget_usd_per_day?: number;++};++/** [email protected] (owner: ai) *//*** ai.credential@1 (OpenVibe.AI; roadmap WS-O task 2): a stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject}): never the key, only its last four characters.@@@ -151966,6 +152009,42 @@ export type AiCredential = {last_used_at?: string | null;};++/** [email protected] (owner: ai) */++/**++ * ai.credential@2 (OpenVibe.AI; Codes C3): one stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject} or /{subject}/{provider}): never the key, only its last four characters. It widens ai.credential@1's provider to the providers of ai.credential-put@2, so a person may keep one key per provider; `key_hint` is present for every provider except `node`, whose machine is named instead.++ */++export type AiCredentialV2 = {++ [k: string]: unknown | undefined;++} & {++ subject: string;++ /**++ * The service that stored it; only it may use or change it.++ */++ owner: string;++ provider: "anthropic" | "openai" | "deepseek" | "minimax" | "openrouter" | "custom" | "node";++ /**++ * provider node: the machine it runs on, or `any` of the person's own++ */++ machine?: string | null;++ base_url?: string | null;++ key_hint?: string;++ /**++ * Model per role on this provider; `chat` is the default for the others.++ */++ models?: {++ chat?: string;++ vision?: string;++ director?: string;++ summary?: string;++ legacy?: string;++ };++ budget_usd_per_day?: number | null;++ spent_usd_today?: number;++ created_at: string;++ updated_at: string;++ last_used_at?: string | null;++};++/** [email protected] (owner: ai) *//*** ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.@@@ -13,20 +13,28 @@ const deprecations = JSON.parse(fs.readFileSync(path.join(ROOT, 'compatibility/dconst ajv = new Ajv2020({ allErrors: true, strict: true, strictRequired: false, allowUnionTypes: true });addFormats(ajv);--const byId = new Map();++// One contract id may hold more than one major (a v2 file, a catalog entry each). The bare id always++// resolves to the newest major listed, and `id@N` to that major, so a v1 caller keeps resolving while++// a v2 caller names it exactly. The catalog lists versions in ascending order.++const byRef = new Map();for (const entry of catalog) {const schema = JSON.parse(fs.readFileSync(path.join(CONTRACTS, entry.schema), 'utf8'));ajv.addSchema(schema);-- byId.set(entry.id, { ...entry, $id: schema.$id, schemaObject: schema });++ const record = { ...entry, $id: schema.$id, schemaObject: schema };++ byRef.set(`${entry.id}@${entry.version.split('.')[0]}`, record);++ byRef.set(entry.id, record);}--/** 'identity.subject-ref' | 'identity.subject-ref@1' | an alias -> catalog entry. */++/** 'identity.subject-ref' | 'identity.subject-ref@1' | an alias -> catalog entry (the newest major, or the named one). */function resolve(ref) {const [raw, major] = String(ref).split('@');const id = aliases[raw] || raw;-- const entry = byId.get(id);-- if (!entry) throw new Error(`unknown contract "${ref}"`);-- if (major && entry.version.split('.')[0] !== major) throw new Error(`contract "${id}" is v${entry.version}, not @${major}`);++ const entry = major ? byRef.get(`${id}@${major}`) : byRef.get(id);++ if (!entry) {++ const known = byRef.get(id);++ if (major && known) throw new Error(`contract "${id}" is v${known.version}, not @${major}`);++ throw new Error(`unknown contract "${ref}"`);++ }return entry;}@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.240.0",++ "version": "0.241.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",@@@ -73,13 +73,18 @@ function onlyOnce(ts, title, owned, emitted) {const stale = [];const bundle = { _about: 'Generated by scripts/generate.js. Do not edit.', contracts: {} };let dts = '/* Generated by scripts/generate.js from contracts/. Do not edit. */\n/* eslint-disable */\n';-- const schemas = new Map(catalog.map((entry) => [entry.id, JSON.parse(fs.readFileSync(path.join(ROOT, 'contracts', entry.schema), 'utf8'))]));++ const schemas = new Map(catalog.map((entry) => [entry.schema, JSON.parse(fs.readFileSync(path.join(ROOT, 'contracts', entry.schema), 'utf8'))]));++ // An id with more than one major in the catalog is keyed `id@N` in the bundle, so neither version++ // overwrites the other; every other id keeps its bare key.++ const majors = new Map();++ for (const e of catalog) majors.set(e.id, (majors.get(e.id) || 0) + 1);const owned = new Set([...schemas.values()].map((s) => s.title));const emitted = new Set();for (const entry of catalog) {const file = path.join(ROOT, 'contracts', entry.schema);-- const schema = schemas.get(entry.id);-- bundle.contracts[entry.id] = { version: entry.version, owner: entry.owner, status: entry.status, schema };++ const schema = schemas.get(entry.schema);++ const bundleKey = majors.get(entry.id) > 1 ? `${entry.id}@${entry.version.split('.')[0]}` : entry.id;++ bundle.contracts[bundleKey] = { version: entry.version, owner: entry.owner, status: entry.status, schema };const ts = await compile(inlineDefs(schema, file), schema.title, {bannerComment: '', cwd: path.dirname(file), declareExternallyReferenced: false,additionalProperties: false, strictIndexSignatures: true, format: true,@@@ -42,10 +42,11 @@ const files = [];for (const f of files) ok(contracts.catalog.some(c => c.schema === f), `${f} is in catalog.json`);for (const c of contracts.catalog) {for (const k of ['id', 'version', 'owner', 'schema', 'visibility', 'compatibility', 'status']) ok(c[k], `${c.id} has ${k}`);-- const s = contracts.schema(c.id);-- ok(s.$id === BASE + c.schema, `${c.id} $id matches its path`);-- ok(c.schema.endsWith(`.v${c.version.split('.')[0]}.json`), `${c.id} file major matches version ${c.version}`);-- ok(s.title && s.description, `${c.id} has title and description`);++ const ref = `${c.id}@${c.version.split('.')[0]}`;++ const s = contracts.schema(ref);++ ok(s.$id === BASE + c.schema, `${ref} $id matches its path`);++ ok(c.schema.endsWith(`.v${c.version.split('.')[0]}.json`), `${ref} file major matches version ${c.version}`);++ ok(s.title && s.description, `${ref} has title and description`);ok(/^\d+\.\d+\.\d+$/.test(c.version), `${c.id} semver`);}for (const d of contracts.catalog.length ? JSON.parse(fs.readFileSync(path.join(ROOT, 'compatibility/deprecations.json'), 'utf8')).deprecations : []) {@@@ -63,7 +64,9 @@ const FULL_CHECK = {'common.resource-name': (v) => contracts.resources.checkName(v), 'common.resource-control-request': (v) => contracts.resources.checkControlRequest(v),'common.resource-control-result': (v) => contracts.resources.checkControlResult(v),};--for (const c of contracts.catalog) {++// `fixtures/<id>/` is one set per contract id, checked against its newest major (a v1 file's fixtures++// stay valid under an additive v2, and a v2-only example belongs there too).++for (const c of [...new Map(contracts.catalog.map((e) => [e.id, e])).values()]) {for (const kind of ['valid', 'invalid']) {const dir = path.join(ROOT, 'fixtures', c.id, kind);const list = fs.existsSync(dir) ? fs.readdirSync(dir).filter(f => f.endsWith('.json')) : [];@@@ -76,6 +79,8 @@ for (const c of contracts.catalog) {}}assert.throws(() => contracts.resolve('identity.subject-ref@2'), /not @2/);++ok(contracts.resolve('ai.credential-put@1').schema === 'ai/credential-put.v1.json' && contracts.resolve('ai.credential-put@2').schema === 'ai/credential-put.v2.json'++ && contracts.resolve('ai.credential-put').version === '2.0.0', 'a contract with two majors resolves by id (newest) or by major');assert.throws(() => contracts.assertValid('identity.subject-ref', { type: 'user', id: '1' }), e => e.code === 'contract.invalid');// ── Manifests ────────────────────────────────────────────────────────────
@@ -4,6 +4,20 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
@@ -4,6 +4,20 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
the notes were in the tag and commit messages (`git tag -n1`).
+## 0.241.0 — 2026-10-30
+
+- **AI: one credential per provider** (Codes C3; research `research-2026-10-30/codes-c3-connections.md` items 1 and 2).
+ `ai.credential-put@2` and `ai.credential@2` are additive on `@1`: the provider enum gains `deepseek`, `minimax`,
+ `openrouter` and `custom` beside `anthropic`, `openai` and `node`, and a PUT may carry `key` (v1's `api_key` stays
+ accepted) and its own `budget_usd_per_day`. `custom` requires an https `base_url`; `node` still takes a machine and no
+ key. A person may now keep one key per provider, and the route without a provider still stores the default one.
+ `ai.credential@2` returns the same body as `@1` with the widened provider, and `key_hint` for every provider except
+ `node`.
+- **Tooling:** the registry can hold more than one major of one contract id — the bare id resolves to the newest listed
+ and `id@N` to that major — so `ai.credential-put@1` keeps resolving while `@2` is the one callers name. The bundle
+ keys a multi-major id as `id@N`, the catalog check looks each entry up by its own major, and a fixture set is checked
+ against the newest major of its id. `ai.credential-put@2` is the first contract to use this.
+
## 0.240.0 — 2026-10-29
## 0.240.0 — 2026-10-29
- **OpenVibe.Vision's API** (plan §5.8b): the service manifest now lists the 20 capabilities its routes serve today —
- **OpenVibe.Vision's API** (plan §5.8b): the service manifest now lists the 20 capabilities its routes serve today —
new file mode 100644
new file mode 100644
@@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential-put.v2.json",
+ "title": "AiCredentialPutV2",
+ "description": "ai.credential-put@2 (OpenVibe.AI; Codes C3): one person's own provider key per provider, stored by the service that holds their consent, PUT /api/v1/credentials/{subject}/{provider} with capability ai.credential.manage. It adds the provider dimension to ai.credential-put@1: a person may keep an Anthropic, OpenAI, DeepSeek, MiniMax, OpenRouter or custom key side by side, each with its own daily budget, and the route without a provider still stores the default one. `key` is the secret (v1's `api_key` stays accepted); `base_url` names the endpoint of a custom provider and is optional elsewhere. OpenVibe.AI encrypts the key at rest, bound to its owner, subject and provider, and never returns it. Provider `node` is unchanged: the person's own machine, named by `machine`, with no key.",
+ "type": "object",
+ "required": [
+ "provider"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "provider": {
+ "enum": [
+ "anthropic",
+ "openai",
+ "deepseek",
+ "minimax",
+ "openrouter",
+ "custom",
+ "node"
+ ],
+ "description": "anthropic = Anthropic's Messages API; openai = any OpenAI-compatible endpoint; deepseek, minimax and openrouter = those providers; custom = the endpoint in base_url (a URL that speaks the OpenAI or the Anthropic format, by the route it is used on); node = the person's own machine (no key, no base_url, no cost)."
+ },
+ "key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400,
+ "description": "The provider key (ai.credential-put@2's name for v1's api_key). Required the first time, and whenever provider or base_url changes (a key is never sent to a new endpoint without being entered again); otherwise the stored key is kept, and it is never returned."
+ },
+ "api_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400,
+ "description": "The ai.credential-put@1 name for `key`, still accepted. When both are sent, `key` wins."
+ },
+ "base_url": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$",
+ "description": "The endpoint of a custom provider (required for it): https, no credentials, query or fragment. OpenVibe.AI connects only to public addresses."
+ },
+ "machine": {
+ "type": "string",
+ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",
+ "description": "provider node: the person's own machine (openvibe.bot/machines) whose OpenVibe Node runs the model, or `any` of their own."
+ },
+ "models": {
+ "type": "object",
+ "additionalProperties": false,
+ "maxProperties": 5,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "vision": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "director": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "legacy": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ }
+ },
+ "description": "Model per role on this provider; `chat` is the default for the others."
+ },
+ "budget_usd_per_day": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 1000,
+ "description": "The person's own daily cap on estimated spend with this provider's key; 0 or absent = no cap."
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "provider": {
+ "const": "node"
+ }
+ },
+ "required": [
+ "provider"
+ ]
+ },
+ "then": {
+ "required": [
+ "machine"
+ ],
+ "not": {
+ "anyOf": [
+ {
+ "required": [
+ "key"
+ ]
+ },
+ {
+ "required": [
+ "api_key"
+ ]
+ },
+ {
+ "required": [
+ "base_url"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "provider": {
+ "const": "custom"
+ }
+ },
+ "required": [
+ "provider"
+ ]
+ },
+ "then": {
+ "required": [
+ "base_url"
+ ]
+ }
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,136 @@
@@ -0,0 +1,136 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential.v2.json",
+ "title": "AiCredentialV2",
+ "description": "ai.credential@2 (OpenVibe.AI; Codes C3): one stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject} or /{subject}/{provider}): never the key, only its last four characters. It widens ai.credential@1's provider to the providers of ai.credential-put@2, so a person may keep one key per provider; `key_hint` is present for every provider except `node`, whose machine is named instead.",
+ "type": "object",
+ "required": [
+ "subject",
+ "owner",
+ "provider",
+ "created_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{1,31}$",
+ "description": "The service that stored it; only it may use or change it."
+ },
+ "provider": {
+ "enum": [
+ "anthropic",
+ "openai",
+ "deepseek",
+ "minimax",
+ "openrouter",
+ "custom",
+ "node"
+ ]
+ },
+ "machine": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",
+ "description": "provider node: the machine it runs on, or `any` of the person's own"
+ },
+ "base_url": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ },
+ "key_hint": {
+ "type": "string",
+ "pattern": "^…[\\s\\S]{1,4}$"
+ },
+ "models": {
+ "type": "object",
+ "additionalProperties": false,
+ "maxProperties": 5,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "vision": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "director": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "legacy": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ }
+ },
+ "description": "Model per role on this provider; `chat` is the default for the others."
+ },
+ "budget_usd_per_day": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "spent_usd_today": {
+ "type": "number",
+ "minimum": 0
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "last_used_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time"
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "provider": {
+ "not": {
+ "const": "node"
+ }
+ }
+ },
+ "required": [
+ "provider"
+ ]
+ },
+ "then": {
+ "required": [
+ "key_hint"
+ ]
+ }
+ }
+ ]
+}
@@ -1306,6 +1306,15 @@
@@ -1306,6 +1306,15 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "ai.credential-put",
+ "version": "2.0.0",
+ "owner": "ai",
+ "schema": "ai/credential-put.v2.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "ai.credential",
"id": "ai.credential",
"version": "1.0.0",
"version": "1.0.0",
@@ -1315,6 +1324,15 @@
@@ -1315,6 +1324,15 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "ai.credential",
+ "version": "2.0.0",
+ "owner": "ai",
+ "schema": "ai/credential.v2.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "ai.attribution-quota-put",
"id": "ai.attribution-quota-put",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"custom","key":"sk-custom-EXAMPLEEXAMPLE","base_url":"http://llm.example.com/anthropic"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"custom","key":"sk-custom-EXAMPLEEXAMPLE"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"groq","key":"sk-groq-EXAMPLEEXAMPLE"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"custom","key":"sk-custom-EXAMPLEEXAMPLEEXAMPLE","base_url":"https://llm.example.com/anthropic","budget_usd_per_day":1}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"deepseek","key":"sk-deepseek-EXAMPLEEXAMPLEEXAMPLE","models":{"chat":"deepseek-chat"},"budget_usd_per_day":3}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"minimax","key":"sk-minimax-EXAMPLEEXAMPLEEXAMPLE","models":{"chat":"MiniMax-M2"}}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"codes","provider":"groq","key_hint":"…MPLE","created_at":"2026-10-30T00:00:00.000Z","updated_at":"2026-10-30T00:00:00.000Z"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"codes","provider":"custom","base_url":"https://llm.example.com/anthropic","key_hint":"…MPLE","models":{},"budget_usd_per_day":null,"spent_usd_today":0,"created_at":"2026-10-30T00:00:00.000Z","updated_at":"2026-10-30T00:00:00.000Z","last_used_at":null}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"codes","provider":"deepseek","base_url":null,"key_hint":"…MPLE","models":{"chat":"deepseek-chat"},"budget_usd_per_day":3,"spent_usd_today":0.02,"created_at":"2026-10-30T00:00:00.000Z","updated_at":"2026-10-30T00:00:00.000Z","last_used_at":null}
@@ -13857,7 +13857,7 @@
@@ -13857,7 +13857,7 @@
}
}
}
}
},
},
- "ai.credential-put": {
+ "ai.credential-put@1": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "ai",
"owner": "ai",
"status": "active",
"status": "active",
@@ -13971,7 +13971,154 @@
@@ -13971,7 +13971,154 @@
]
]
}
}
},
},
- "ai.credential": {
+ "ai.credential-put@2": {
+ "version": "2.0.0",
+ "owner": "ai",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential-put.v2.json",
+ "title": "AiCredentialPutV2",
+ "description": "ai.credential-put@2 (OpenVibe.AI; Codes C3): one person's own provider key per provider, stored by the service that holds their consent, PUT /api/v1/credentials/{subject}/{provider} with capability ai.credential.manage. It adds the provider dimension to ai.credential-put@1: a person may keep an Anthropic, OpenAI, DeepSeek, MiniMax, OpenRouter or custom key side by side, each with its own daily budget, and the route without a provider still stores the default one. `key` is the secret (v1's `api_key` stays accepted); `base_url` names the endpoint of a custom provider and is optional elsewhere. OpenVibe.AI encrypts the key at rest, bound to its owner, subject and provider, and never returns it. Provider `node` is unchanged: the person's own machine, named by `machine`, with no key.",
+ "type": "object",
+ "required": [
+ "provider"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "provider": {
+ "enum": [
+ "anthropic",
+ "openai",
+ "deepseek",
+ "minimax",
+ "openrouter",
+ "custom",
+ "node"
+ ],
+ "description": "anthropic = Anthropic's Messages API; openai = any OpenAI-compatible endpoint; deepseek, minimax and openrouter = those providers; custom = the endpoint in base_url (a URL that speaks the OpenAI or the Anthropic format, by the route it is used on); node = the person's own machine (no key, no base_url, no cost)."
+ },
+ "key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400,
+ "description": "The provider key (ai.credential-put@2's name for v1's api_key). Required the first time, and whenever provider or base_url changes (a key is never sent to a new endpoint without being entered again); otherwise the stored key is kept, and it is never returned."
+ },
+ "api_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400,
+ "description": "The ai.credential-put@1 name for `key`, still accepted. When both are sent, `key` wins."
+ },
+ "base_url": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$",
+ "description": "The endpoint of a custom provider (required for it): https, no credentials, query or fragment. OpenVibe.AI connects only to public addresses."
+ },
+ "machine": {
+ "type": "string",
+ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",
+ "description": "provider node: the person's own machine (openvibe.bot/machines) whose OpenVibe Node runs the model, or `any` of their own."
+ },
+ "models": {
+ "type": "object",
+ "additionalProperties": false,
+ "maxProperties": 5,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "vision": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "director": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "legacy": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ }
+ },
+ "description": "Model per role on this provider; `chat` is the default for the others."
+ },
+ "budget_usd_per_day": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 1000,
+ "description": "The person's own daily cap on estimated spend with this provider's key; 0 or absent = no cap."
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "provider": {
+ "const": "node"
+ }
+ },
+ "required": [
+ "provider"
+ ]
+ },
+ "then": {
+ "required": [
+ "machine"
+ ],
+ "not": {
+ "anyOf": [
+ {
+ "required": [
+ "key"
+ ]
+ },
+ {
+ "required": [
+ "api_key"
+ ]
+ },
+ {
+ "required": [
+ "base_url"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "provider": {
+ "const": "custom"
+ }
+ },
+ "required": [
+ "provider"
+ ]
+ },
+ "then": {
+ "required": [
+ "base_url"
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "ai.credential@1": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "ai",
"owner": "ai",
"status": "active",
"status": "active",
@@ -14109,6 +14256,147 @@
@@ -14109,6 +14256,147 @@
]
]
}
}
},
},
+ "ai.credential@2": {
+ "version": "2.0.0",
+ "owner": "ai",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential.v2.json",
+ "title": "AiCredentialV2",
+ "description": "ai.credential@2 (OpenVibe.AI; Codes C3): one stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject} or /{subject}/{provider}): never the key, only its last four characters. It widens ai.credential@1's provider to the providers of ai.credential-put@2, so a person may keep one key per provider; `key_hint` is present for every provider except `node`, whose machine is named instead.",
+ "type": "object",
+ "required": [
+ "subject",
+ "owner",
+ "provider",
+ "created_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{1,31}$",
+ "description": "The service that stored it; only it may use or change it."
+ },
+ "provider": {
+ "enum": [
+ "anthropic",
+ "openai",
+ "deepseek",
+ "minimax",
+ "openrouter",
+ "custom",
+ "node"
+ ]
+ },
+ "machine": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^(dev_[0-9A-HJKMNP-TV-Z]{26}|any)$",
+ "description": "provider node: the machine it runs on, or `any` of the person's own"
+ },
+ "base_url": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ },
+ "key_hint": {
+ "type": "string",
+ "pattern": "^…[\\s\\S]{1,4}$"
+ },
+ "models": {
+ "type": "object",
+ "additionalProperties": false,
+ "maxProperties": 5,
+ "properties": {
+ "chat": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "vision": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "director": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "summary": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "legacy": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ }
+ },
+ "description": "Model per role on this provider; `chat` is the default for the others."
+ },
+ "budget_usd_per_day": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "spent_usd_today": {
+ "type": "number",
+ "minimum": 0
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "last_used_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time"
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "provider": {
+ "not": {
+ "const": "node"
+ }
+ }
+ },
+ "required": [
+ "provider"
+ ]
+ },
+ "then": {
+ "required": [
+ "key_hint"
+ ]
+ }
+ }
+ ]
+ }
+ },
"ai.attribution-quota-put": {
"ai.attribution-quota-put": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "ai",
"owner": "ai",
@@ -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.240.0",
- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.Inventory API",
"title": "OpenVibe.Inventory API",
- "version": "0.240.0",
- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.Network API",
"title": "OpenVibe.Network API",
- "version": "0.240.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.241.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.240.0",
- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.240.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.241.0",
+ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.241.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"
@@ -151930,6 +151930,49 @@ export type AiCredentialPut = {
@@ -151930,6 +151930,49 @@ export type AiCredentialPut = {
budget_usd_per_day?: number;
budget_usd_per_day?: number;
};
};
+/** [email protected] (owner: ai) */
+/**
+ * ai.credential-put@2 (OpenVibe.AI; Codes C3): one person's own provider key per provider, stored by the service that holds their consent, PUT /api/v1/credentials/{subject}/{provider} with capability ai.credential.manage. It adds the provider dimension to ai.credential-put@1: a person may keep an Anthropic, OpenAI, DeepSeek, MiniMax, OpenRouter or custom key side by side, each with its own daily budget, and the route without a provider still stores the default one. `key` is the secret (v1's `api_key` stays accepted); `base_url` names the endpoint of a custom provider and is optional elsewhere. OpenVibe.AI encrypts the key at rest, bound to its owner, subject and provider, and never returns it. Provider `node` is unchanged: the person's own machine, named by `machine`, with no key.
+ */
+export type AiCredentialPutV2 = {
+ [k: string]: unknown | undefined;
+} & {
+ /**
+ * anthropic = Anthropic's Messages API; openai = any OpenAI-compatible endpoint; deepseek, minimax and openrouter = those providers; custom = the endpoint in base_url (a URL that speaks the OpenAI or the Anthropic format, by the route it is used on); node = the person's own machine (no key, no base_url, no cost).
+ */
+ provider: "anthropic" | "openai" | "deepseek" | "minimax" | "openrouter" | "custom" | "node";
+ /**
+ * The provider key (ai.credential-put@2's name for v1's api_key). Required the first time, and whenever provider or base_url changes (a key is never sent to a new endpoint without being entered again); otherwise the stored key is kept, and it is never returned.
+ */
+ key?: string;
+ /**
+ * The ai.credential-put@1 name for `key`, still accepted. When both are sent, `key` wins.
+ */
+ api_key?: string;
+ /**
+ * The endpoint of a custom provider (required for it): https, no credentials, query or fragment. OpenVibe.AI connects only to public addresses.
+ */
+ base_url?: string;
+ /**
+ * provider node: the person's own machine (openvibe.bot/machines) whose OpenVibe Node runs the model, or `any` of their own.
+ */
+ machine?: string;
+ /**
+ * Model per role on this provider; `chat` is the default for the others.
+ */
+ models?: {
+ chat?: string;
+ vision?: string;
+ director?: string;
+ summary?: string;
+ legacy?: string;
+ };
+ /**
+ * The person's own daily cap on estimated spend with this provider's key; 0 or absent = no cap.
+ */
+ budget_usd_per_day?: number;
+};
+
/** [email protected] (owner: ai) */
/** [email protected] (owner: ai) */
/**
/**
* ai.credential@1 (OpenVibe.AI; roadmap WS-O task 2): a stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject}): never the key, only its last four characters.
* ai.credential@1 (OpenVibe.AI; roadmap WS-O task 2): a stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject}): never the key, only its last four characters.
@@ -151966,6 +152009,42 @@ export type AiCredential = {
@@ -151966,6 +152009,42 @@ export type AiCredential = {
last_used_at?: string | null;
last_used_at?: string | null;
};
};
+/** [email protected] (owner: ai) */
+/**
+ * ai.credential@2 (OpenVibe.AI; Codes C3): one stored credential as its owner service reads it (GET or PUT /api/v1/credentials/{subject} or /{subject}/{provider}): never the key, only its last four characters. It widens ai.credential@1's provider to the providers of ai.credential-put@2, so a person may keep one key per provider; `key_hint` is present for every provider except `node`, whose machine is named instead.
+ */
+export type AiCredentialV2 = {
+ [k: string]: unknown | undefined;
+} & {
+ subject: string;
+ /**
+ * The service that stored it; only it may use or change it.
+ */
+ owner: string;
+ provider: "anthropic" | "openai" | "deepseek" | "minimax" | "openrouter" | "custom" | "node";
+ /**
+ * provider node: the machine it runs on, or `any` of the person's own
+ */
+ machine?: string | null;
+ base_url?: string | null;
+ key_hint?: string;
+ /**
+ * Model per role on this provider; `chat` is the default for the others.
+ */
+ models?: {
+ chat?: string;
+ vision?: string;
+ director?: string;
+ summary?: string;
+ legacy?: string;
+ };
+ budget_usd_per_day?: number | null;
+ spent_usd_today?: number;
+ created_at: string;
+ updated_at: string;
+ last_used_at?: string | null;
+};
+
/** [email protected] (owner: ai) */
/** [email protected] (owner: ai) */
/**
/**
* ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.
* ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.
@@ -13,20 +13,28 @@ const deprecations = JSON.parse(fs.readFileSync(path.join(ROOT, 'compatibility/d
@@ -13,20 +13,28 @@ const deprecations = JSON.parse(fs.readFileSync(path.join(ROOT, 'compatibility/d
const ajv = new Ajv2020({ allErrors: true, strict: true, strictRequired: false, allowUnionTypes: true });
const ajv = new Ajv2020({ allErrors: true, strict: true, strictRequired: false, allowUnionTypes: true });
addFormats(ajv);
addFormats(ajv);
-const byId = new Map();
+// One contract id may hold more than one major (a v2 file, a catalog entry each). The bare id always
+// resolves to the newest major listed, and `id@N` to that major, so a v1 caller keeps resolving while
+// a v2 caller names it exactly. The catalog lists versions in ascending order.
+const byRef = new Map();
for (const entry of catalog) {
for (const entry of catalog) {
const schema = JSON.parse(fs.readFileSync(path.join(CONTRACTS, entry.schema), 'utf8'));
const schema = JSON.parse(fs.readFileSync(path.join(CONTRACTS, entry.schema), 'utf8'));
ajv.addSchema(schema);
ajv.addSchema(schema);
- byId.set(entry.id, { ...entry, $id: schema.$id, schemaObject: schema });
+ const record = { ...entry, $id: schema.$id, schemaObject: schema };
+ byRef.set(`${entry.id}@${entry.version.split('.')[0]}`, record);
+ byRef.set(entry.id, record);
}
}
-/** 'identity.subject-ref' | 'identity.subject-ref@1' | an alias -> catalog entry. */
+/** 'identity.subject-ref' | 'identity.subject-ref@1' | an alias -> catalog entry (the newest major, or the named one). */
function resolve(ref) {
function resolve(ref) {
const [raw, major] = String(ref).split('@');
const [raw, major] = String(ref).split('@');
const id = aliases[raw] || raw;
const id = aliases[raw] || raw;
- const entry = byId.get(id);
- if (!entry) throw new Error(`unknown contract "${ref}"`);
- if (major && entry.version.split('.')[0] !== major) throw new Error(`contract "${id}" is v${entry.version}, not @${major}`);
+ const entry = major ? byRef.get(`${id}@${major}`) : byRef.get(id);
+ if (!entry) {
+ const known = byRef.get(id);
+ if (major && known) throw new Error(`contract "${id}" is v${known.version}, not @${major}`);
+ throw new Error(`unknown contract "${ref}"`);
+ }
return entry;
return entry;
}
}
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.240.0",
+ "version": "0.241.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",
@@ -73,13 +73,18 @@ function onlyOnce(ts, title, owned, emitted) {
@@ -73,13 +73,18 @@ function onlyOnce(ts, title, owned, emitted) {
const stale = [];
const stale = [];
const bundle = { _about: 'Generated by scripts/generate.js. Do not edit.', contracts: {} };
const bundle = { _about: 'Generated by scripts/generate.js. Do not edit.', contracts: {} };
let dts = '/* Generated by scripts/generate.js from contracts/. Do not edit. */\n/* eslint-disable */\n';
let dts = '/* Generated by scripts/generate.js from contracts/. Do not edit. */\n/* eslint-disable */\n';
- const schemas = new Map(catalog.map((entry) => [entry.id, JSON.parse(fs.readFileSync(path.join(ROOT, 'contracts', entry.schema), 'utf8'))]));
+ const schemas = new Map(catalog.map((entry) => [entry.schema, JSON.parse(fs.readFileSync(path.join(ROOT, 'contracts', entry.schema), 'utf8'))]));
+ // An id with more than one major in the catalog is keyed `id@N` in the bundle, so neither version
+ // overwrites the other; every other id keeps its bare key.
+ const majors = new Map();
+ for (const e of catalog) majors.set(e.id, (majors.get(e.id) || 0) + 1);
const owned = new Set([...schemas.values()].map((s) => s.title));
const owned = new Set([...schemas.values()].map((s) => s.title));
const emitted = new Set();
const emitted = new Set();
for (const entry of catalog) {
for (const entry of catalog) {
const file = path.join(ROOT, 'contracts', entry.schema);
const file = path.join(ROOT, 'contracts', entry.schema);
- const schema = schemas.get(entry.id);
- bundle.contracts[entry.id] = { version: entry.version, owner: entry.owner, status: entry.status, schema };
+ const schema = schemas.get(entry.schema);
+ const bundleKey = majors.get(entry.id) > 1 ? `${entry.id}@${entry.version.split('.')[0]}` : entry.id;
+ bundle.contracts[bundleKey] = { version: entry.version, owner: entry.owner, status: entry.status, schema };
const ts = await compile(inlineDefs(schema, file), schema.title, {
const ts = await compile(inlineDefs(schema, file), schema.title, {
bannerComment: '', cwd: path.dirname(file), declareExternallyReferenced: false,
bannerComment: '', cwd: path.dirname(file), declareExternallyReferenced: false,
additionalProperties: false, strictIndexSignatures: true, format: true,
additionalProperties: false, strictIndexSignatures: true, format: true,
@@ -42,10 +42,11 @@ const files = [];
@@ -42,10 +42,11 @@ const files = [];
for (const f of files) ok(contracts.catalog.some(c => c.schema === f), `${f} is in catalog.json`);
for (const f of files) ok(contracts.catalog.some(c => c.schema === f), `${f} is in catalog.json`);
for (const c of contracts.catalog) {
for (const c of contracts.catalog) {
for (const k of ['id', 'version', 'owner', 'schema', 'visibility', 'compatibility', 'status']) ok(c[k], `${c.id} has ${k}`);
for (const k of ['id', 'version', 'owner', 'schema', 'visibility', 'compatibility', 'status']) ok(c[k], `${c.id} has ${k}`);
- const s = contracts.schema(c.id);
- ok(s.$id === BASE + c.schema, `${c.id} $id matches its path`);
- ok(c.schema.endsWith(`.v${c.version.split('.')[0]}.json`), `${c.id} file major matches version ${c.version}`);
- ok(s.title && s.description, `${c.id} has title and description`);
+ const ref = `${c.id}@${c.version.split('.')[0]}`;
+ const s = contracts.schema(ref);
+ ok(s.$id === BASE + c.schema, `${ref} $id matches its path`);
+ ok(c.schema.endsWith(`.v${c.version.split('.')[0]}.json`), `${ref} file major matches version ${c.version}`);
+ ok(s.title && s.description, `${ref} has title and description`);
ok(/^\d+\.\d+\.\d+$/.test(c.version), `${c.id} semver`);
ok(/^\d+\.\d+\.\d+$/.test(c.version), `${c.id} semver`);
}
}
for (const d of contracts.catalog.length ? JSON.parse(fs.readFileSync(path.join(ROOT, 'compatibility/deprecations.json'), 'utf8')).deprecations : []) {
for (const d of contracts.catalog.length ? JSON.parse(fs.readFileSync(path.join(ROOT, 'compatibility/deprecations.json'), 'utf8')).deprecations : []) {
@@ -63,7 +64,9 @@ const FULL_CHECK = {
@@ -63,7 +64,9 @@ const FULL_CHECK = {
'common.resource-name': (v) => contracts.resources.checkName(v), 'common.resource-control-request': (v) => contracts.resources.checkControlRequest(v),
'common.resource-name': (v) => contracts.resources.checkName(v), 'common.resource-control-request': (v) => contracts.resources.checkControlRequest(v),
'common.resource-control-result': (v) => contracts.resources.checkControlResult(v),
'common.resource-control-result': (v) => contracts.resources.checkControlResult(v),
};
};
-for (const c of contracts.catalog) {
+// `fixtures/<id>/` is one set per contract id, checked against its newest major (a v1 file's fixtures
+// stay valid under an additive v2, and a v2-only example belongs there too).
+for (const c of [...new Map(contracts.catalog.map((e) => [e.id, e])).values()]) {
for (const kind of ['valid', 'invalid']) {
for (const kind of ['valid', 'invalid']) {
const dir = path.join(ROOT, 'fixtures', c.id, kind);
const dir = path.join(ROOT, 'fixtures', c.id, kind);
const list = fs.existsSync(dir) ? fs.readdirSync(dir).filter(f => f.endsWith('.json')) : [];
const list = fs.existsSync(dir) ? fs.readdirSync(dir).filter(f => f.endsWith('.json')) : [];
@@ -76,6 +79,8 @@ for (const c of contracts.catalog) {
@@ -76,6 +79,8 @@ for (const c of contracts.catalog) {
}
}
}
}
assert.throws(() => contracts.resolve('identity.subject-ref@2'), /not @2/);
assert.throws(() => contracts.resolve('identity.subject-ref@2'), /not @2/);
+ok(contracts.resolve('ai.credential-put@1').schema === 'ai/credential-put.v1.json' && contracts.resolve('ai.credential-put@2').schema === 'ai/credential-put.v2.json'
+ && contracts.resolve('ai.credential-put').version === '2.0.0', 'a contract with two majors resolves by id (newest) or by major');
assert.throws(() => contracts.assertValid('identity.subject-ref', { type: 'user', id: '1' }), e => e.code === 'contract.invalid');
assert.throws(() => contracts.assertValid('identity.subject-ref', { type: 'user', id: '1' }), e => e.code === 'contract.invalid');
// ── Manifests ────────────────────────────────────────────────────────────
// ── Manifests ────────────────────────────────────────────────────────────