openvibers/openvibe.contracts Commits
v0.73.0: a person's own provider key lives in OpenVibe.AI (roadmap WS-O task 2). ai.credential.manage (first-party): the service holding a person's consent stores their key (PUT /api/v1/credentials/{subject}, ai.credential-put@1: openai or anthropic, an https base_url, models per role, an optional budget_usd_per_day), reads it back without the key (ai.credential@1: a four-character hint and today's spend) or deletes it; only the storing service uses or changes it. ai.run-request@1 gains the optional credential { subject }: that provider with that key only, no fallback, never cached, the shared paid budget untouched, the credential's daily budget enforced; chat operations only.
Changes
@@@ -6,6 +6,12 @@ the notes were in the tag and commit messages (`git tag -n1`).## Unreleased++## 0.73.0 — 2026-09-28++++**A person's own provider key lives in OpenVibe.AI** (roadmap WS-O task 2).++- `ai.credential.manage` (first-party): the service that holds a person's consent (Live, for a streamer's AI viewers) stores their key at `PUT /api/v1/credentials/{subject}` (`ai.credential-put@1`: provider openai or anthropic, an https `base_url`, the key, models per role, and an optional `budget_usd_per_day`). It reads it back without the key (`ai.credential@1`, a four-character hint and today's spend) or deletes it. Only the storing service uses or changes a credential.++- `ai.run-request@1` gains the optional `credential { subject }`. The run calls that provider with that key only: no fallback, never cached, the shared paid budget untouched, and the credential's own daily budget enforced. Chat operations only.++## 0.72.0 — 2026-09-27**Mod principals in Network** (roadmap WS-M task 3, ADR-013).nnew file mode 100644@@@ -0,0 +1,70 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential-put.v1.json",++ "title": "AiCredentialPut",++ "description": "ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.",++ "type": "object",++ "required": [++ "provider",++ "api_key"++ ],++ "additionalProperties": false,++ "properties": {++ "provider": {++ "enum": [++ "openai",++ "anthropic"++ ],++ "description": "openai = any OpenAI-compatible endpoint."++ },++ "base_url": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"++ },++ "api_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400++ },++ "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 Live role; `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 key; 0 or absent = no cap."++ }++ }++}nnew file mode 100644@@@ -0,0 +1,103 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential.v1.json",++ "title": "AiCredential",++ "description": "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.",++ "type": "object",++ "required": [++ "subject",++ "owner",++ "provider",++ "key_hint",++ "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": [++ "openai",++ "anthropic"++ ]++ },++ "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 Live role; `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"++ }++ }++}@@@ -4,28 +4,69 @@"title": "AiRunRequest","description": "Body of POST /api/v1/runs on OpenVibe.AI (capability ai.run.create; ADR-015). Runs the newest active version of a workflow (or the given active or deprecated version) on input that must match that workflow version's own input schema; per-workflow input and output schemas live in AI's registry (GET /api/v1/workflows/:key), not here. The token's ns claim limits which workflow namespaces may run (403 capability.namespace_denied). ?wait=ms waits for the result: 201 finished or served from cache, 202 still queued/running (poll GET /api/v1/runs/:id), 200 an idempotent replay. Errors are problem+json: 404 workflow.not_found, 409 workflow.inactive, 409 idempotency.conflict, 413 input.too_large, 422 input.invalid, 429 quota.exceeded or queue.full with Retry-After. The direct operations POST /api/v1/{chat,generate,summarize,classify,extract,enrich,embed} take the same fields (except workflow and version) with the input fields at the top level and run workflow ai.<op>. target (EntityRef): what the output is about, part of the cache scope and a run filter. attribution (EntityRef): what the spend is attributed to for quotas and usage. on_behalf_of (SubjectRef): the person or actor the caller acts for, part of the cache scope and per-actor quotas.","type": "object",-- "required": ["workflow"],++ "required": [++ "workflow"++ ],"additionalProperties": false,"properties": {"workflow": {-- "type": "string", "pattern": "^[a-z][a-z0-9_-]*(\\.[a-z0-9_-]+)+$", "maxLength": 200,++ "type": "string",++ "pattern": "^[a-z][a-z0-9_-]*(\\.[a-z0-9_-]+)+$",++ "maxLength": 200,"description": "Workflow key, <namespace>.<name> (live.chat_reply, news.summarize_story, network.site_copy…)."},-- "version": { "type": "integer", "minimum": 1, "description": "Pin a workflow version (active or deprecated). Omitted: the newest active version." },-- "input": { "type": "object", "description": "Workflow input; validated against the workflow version's input_schema. Default {}." },-- "target": { "$ref": "../common/entity-ref.v1.json" },-- "attribution": { "$ref": "../common/entity-ref.v1.json" },-- "on_behalf_of": { "$ref": "../identity/subject-ref.v1.json" },++ "version": {++ "type": "integer",++ "minimum": 1,++ "description": "Pin a workflow version (active or deprecated). Omitted: the newest active version."++ },++ "input": {++ "type": "object",++ "description": "Workflow input; validated against the workflow version's input_schema. Default {}."++ },++ "target": {++ "$ref": "../common/entity-ref.v1.json"++ },++ "attribution": {++ "$ref": "../common/entity-ref.v1.json"++ },++ "on_behalf_of": {++ "$ref": "../identity/subject-ref.v1.json"++ },"idempotency_key": {-- "type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$",++ "type": "string",++ "pattern": "^[A-Za-z0-9._:-]{8,128}$","description": "Same (requester, key) returns the existing run; a different workflow or input under it is 409 idempotency.conflict. The Idempotency-Key header is used when this is absent."},"options": {-- "type": "object", "additionalProperties": false,++ "type": "object",++ "additionalProperties": false,"properties": {-- "cache": { "type": "boolean", "default": true, "description": "false skips the scoped cache lookup and store." },-- "debug": { "type": "boolean", "default": false, "description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on." }++ "cache": {++ "type": "boolean",++ "default": true,++ "description": "false skips the scoped cache lookup and store."++ },++ "debug": {++ "type": "boolean",++ "default": false,++ "description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."++ }}++ },++ "credential": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "subject"++ ],++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ },++ "description": "Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision)."}}}@@@ -1205,6 +1205,24 @@"compatibility": "backward","status": "active"},++ {++ "id": "ai.credential-put",++ "version": "1.0.0",++ "owner": "ai",++ "schema": "ai/credential-put.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "ai.credential",++ "version": "1.0.0",++ "owner": "ai",++ "schema": "ai/credential.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "ai.run-request","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"openai","base_url":"http://10.0.0.1/v1","api_key":"sk-EXAMPLEEXAMPLE"}nnew file mode 100644@@@ -0,0 +1 @@++{"provider":"openai","base_url":"https://openrouter.ai/api/v1","api_key":"sk-or-v1-EXAMPLEEXAMPLEEXAMPLE","models":{"chat":"gpt-4o-mini"},"budget_usd_per_day":2}nnew file mode 100644@@@ -0,0 +1 @@++{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"live","provider":"openai","api_key":"sk-EXAMPLE","key_hint":"…MPLE","created_at":"2026-09-28T00:00:00.000Z","updated_at":"2026-09-28T00:00:00.000Z"}nnew file mode 100644@@@ -0,0 +1 @@++{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"live","provider":"openai","base_url":"https://openrouter.ai/api/v1","key_hint":"…MPLE","models":{"chat":"gpt-4o-mini"},"budget_usd_per_day":2,"spent_usd_today":0.12,"created_at":"2026-09-28T00:00:00.000Z","updated_at":"2026-09-28T00:00:00.000Z","last_used_at":null}nnew file mode 100644@@@ -0,0 +1 @@++{"workflow":"live.viewers.line","input":{"system":"s","user":"u"},"credential":{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"}}@@@ -11818,6 +11818,189 @@}}},++ "ai.credential-put": {++ "version": "1.0.0",++ "owner": "ai",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential-put.v1.json",++ "title": "AiCredentialPut",++ "description": "ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.",++ "type": "object",++ "required": [++ "provider",++ "api_key"++ ],++ "additionalProperties": false,++ "properties": {++ "provider": {++ "enum": [++ "openai",++ "anthropic"++ ],++ "description": "openai = any OpenAI-compatible endpoint."++ },++ "base_url": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"++ },++ "api_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400++ },++ "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 Live role; `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 key; 0 or absent = no cap."++ }++ }++ }++ },++ "ai.credential": {++ "version": "1.0.0",++ "owner": "ai",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/credential.v1.json",++ "title": "AiCredential",++ "description": "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.",++ "type": "object",++ "required": [++ "subject",++ "owner",++ "provider",++ "key_hint",++ "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": [++ "openai",++ "anthropic"++ ]++ },++ "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 Live role; `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"++ }++ }++ }++ },"ai.run-request": {"version": "1.0.0","owner": "ai",@@@ -11877,6 +12060,20 @@"description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."}}++ },++ "credential": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "subject"++ ],++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ },++ "description": "Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision)."}}}@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.72.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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"@@@ -267,6 +267,354 @@}}},++ "/api/v1/credentials/{subject}": {++ "delete": {++ "operationId": "delete_api_v1_credentials_subject",++ "summary": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential).",++ "description": "**ai.credential.manage** (first-party): Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",++ "tags": [++ "ai.credential"++ ],++ "x-openvibe-capabilities": [++ "ai.credential.manage"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "ai-credentials",++ "security": [++ {++ "openvibeToken": [++ "ai.credential.manage"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/ai.credential-put.v1"++ },++ "parameters": [++ {++ "name": "subject",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "provider",++ "in": "query",++ "required": true,++ "schema": {++ "enum": [++ "openai",++ "anthropic"++ ],++ "description": "openai = any OpenAI-compatible endpoint."++ },++ "description": "openai = any OpenAI-compatible endpoint."++ },++ {++ "name": "base_url",++ "in": "query",++ "required": false,++ "schema": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"++ }++ },++ {++ "name": "api_key",++ "in": "query",++ "required": true,++ "schema": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400++ }++ },++ {++ "name": "models",++ "in": "query",++ "required": false,++ "schema": {++ "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 Live role; `chat` is the default for the others."++ },++ "description": "Model per Live role; `chat` is the default for the others."++ },++ {++ "name": "budget_usd_per_day",++ "in": "query",++ "required": false,++ "schema": {++ "type": "number",++ "minimum": 0,++ "maximum": 1000,++ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."++ },++ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.credential.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "get": {++ "operationId": "get_api_v1_credentials_subject",++ "summary": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential).",++ "description": "**ai.credential.manage** (first-party): Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",++ "tags": [++ "ai.credential"++ ],++ "x-openvibe-capabilities": [++ "ai.credential.manage"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "ai-credentials",++ "security": [++ {++ "openvibeToken": [++ "ai.credential.manage"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/ai.credential-put.v1"++ },++ "parameters": [++ {++ "name": "subject",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ },++ {++ "name": "provider",++ "in": "query",++ "required": true,++ "schema": {++ "enum": [++ "openai",++ "anthropic"++ ],++ "description": "openai = any OpenAI-compatible endpoint."++ },++ "description": "openai = any OpenAI-compatible endpoint."++ },++ {++ "name": "base_url",++ "in": "query",++ "required": false,++ "schema": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"++ }++ },++ {++ "name": "api_key",++ "in": "query",++ "required": true,++ "schema": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400++ }++ },++ {++ "name": "models",++ "in": "query",++ "required": false,++ "schema": {++ "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 Live role; `chat` is the default for the others."++ },++ "description": "Model per Live role; `chat` is the default for the others."++ },++ {++ "name": "budget_usd_per_day",++ "in": "query",++ "required": false,++ "schema": {++ "type": "number",++ "minimum": 0,++ "maximum": 1000,++ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."++ },++ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.credential.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ },++ "put": {++ "operationId": "put_api_v1_credentials_subject",++ "summary": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential).",++ "description": "**ai.credential.manage** (first-party): Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",++ "tags": [++ "ai.credential"++ ],++ "x-openvibe-capabilities": [++ "ai.credential.manage"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "ai-credentials",++ "security": [++ {++ "openvibeToken": [++ "ai.credential.manage"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.credential-put.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "subject",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.credential.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },"/api/v1/embed": {"post": {"operationId": "post_api_v1_embed",@@@ -2154,6 +2502,175 @@},"components": {"schemas": {++ "ai.credential-put.v1": {++ "title": "AiCredentialPut",++ "description": "ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.",++ "type": "object",++ "required": [++ "provider",++ "api_key"++ ],++ "additionalProperties": false,++ "properties": {++ "provider": {++ "enum": [++ "openai",++ "anthropic"++ ],++ "description": "openai = any OpenAI-compatible endpoint."++ },++ "base_url": {++ "type": "string",++ "maxLength": 300,++ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"++ },++ "api_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 400++ },++ "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 Live role; `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 key; 0 or absent = no cap."++ }++ }++ },++ "ai.credential.v1": {++ "title": "AiCredential",++ "description": "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.",++ "type": "object",++ "required": [++ "subject",++ "owner",++ "provider",++ "key_hint",++ "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": [++ "openai",++ "anthropic"++ ]++ },++ "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 Live role; `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"++ }++ }++ },"ai.definition-version-request.v1": {"title": "AiDefinitionVersionRequest","description": "ai.definition-version-request@1: bodies of ai.workflow.manage on OpenVibe.AI. An edit is always a new version (the previous one stays readable); fields left out are taken from the newest existing version. POST /api/v1/templates/:key/versions: a prompt template (input_schema and output_schema must compile as JSON Schema; visibility public, first-party or internal). POST /api/v1/workflows/:key/versions (key <namespace>.<name>): steps (at least one; kind llm (naming an existing template), passthrough, transcribe or embed), schemas, default route, cache mode. POST /api/v1/routes/:key/versions: primary { provider, model } and fallbacks (every provider must exist), or alias_of another route. POST …/:key/versions/:version/status: { status } (templates and workflows draft|active|deprecated|archived; routes active|disabled). Refusals are 422 ai.invalid.",@@@ -3469,6 +3986,20 @@"description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."}}++ },++ "credential": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "subject"++ ],++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ },++ "description": "Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision)."}}},@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.72.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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"@@@ -5,8 +5,8 @@"service": "ai","name": "OpenVibe.AI","origin": "https://ai.openvibe.network",-- "operations": 37,-- "capabilities": 5++ "operations": 40,++ "capabilities": 6},{"service": "billing",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.72.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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": "OpenRe.Stream API",-- "version": "0.72.0",-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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"@@@ -15769,6 +15769,63 @@ export interface BlogThemeRequest {theme: "vibe" | "paper" | "slate" | "sand" | "nord" | "high-contrast";}++/** [email protected] (owner: ai) */++/**++ * ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.++ */++export interface AiCredentialPut {++ /**++ * openai = any OpenAI-compatible endpoint.++ */++ provider: "openai" | "anthropic";++ base_url?: string;++ api_key: string;++ /**++ * Model per Live role; `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 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.++ */++export interface AiCredential {++ subject: string;++ /**++ * The service that stored it; only it may use or change it.++ */++ owner: string;++ provider: "openai" | "anthropic";++ base_url?: string | null;++ key_hint: string;++ /**++ * Model per Live role; `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) *//*** Body of POST /api/v1/runs on OpenVibe.AI (capability ai.run.create; ADR-015). Runs the newest active version of a workflow (or the given active or deprecated version) on input that must match that workflow version's own input schema; per-workflow input and output schemas live in AI's registry (GET /api/v1/workflows/:key), not here. The token's ns claim limits which workflow namespaces may run (403 capability.namespace_denied). ?wait=ms waits for the result: 201 finished or served from cache, 202 still queued/running (poll GET /api/v1/runs/:id), 200 an idempotent replay. Errors are problem+json: 404 workflow.not_found, 409 workflow.inactive, 409 idempotency.conflict, 413 input.too_large, 422 input.invalid, 429 quota.exceeded or queue.full with Retry-After. The direct operations POST /api/v1/{chat,generate,summarize,classify,extract,enrich,embed} take the same fields (except workflow and version) with the input fields at the top level and run workflow ai.<op>. target (EntityRef): what the output is about, part of the cache scope and a run filter. attribution (EntityRef): what the spend is attributed to for quotas and usage. on_behalf_of (SubjectRef): the person or actor the caller acts for, part of the cache scope and per-actor quotas.@@@ -15803,6 +15860,12 @@ export interface AiRunRequest {*/debug?: boolean;};++ /**++ * Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision).++ */++ credential?: {++ subject: string;++ };}/** [email protected] (owner: ai) */nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "id": "ai.credential.manage",++ "version": "1.0",++ "owner": "ai",++ "status": "active",++ "visibility": "first-party",++ "description": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",++ "permissions": [++ "ai:credentials"++ ],++ "resourceConstraints": [++ "owner"++ ],++ "quotaClass": "ai-credentials",++ "events": [],++ "implementedBy": [++ "PUT /api/v1/credentials/:subject",++ "GET /api/v1/credentials/:subject",++ "DELETE /api/v1/credentials/:subject"++ ],++ "inputSchema": "ai.credential-put@1",++ "outputSchema": "ai.credential@1"++}@@@ -20,11 +20,12 @@"note": "called by other services at 127.0.0.1:4700; ai.openvibe.network serves the OpenVibe.Sites placeholder page"},"capabilities": [++ "ai.credential.manage",++ "ai.provider.manage","ai.run.create","ai.run.read",-- "ai.workflow.manage",-- "ai.provider.manage",-- "ai.usage.read"++ "ai.usage.read",++ "ai.workflow.manage"],"eventsProduced": ["ai.run.queued",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.72.0",++ "version": "0.73.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",
@@ -6,6 +6,12 @@ the notes were in the tag and commit messages (`git tag -n1`).
@@ -6,6 +6,12 @@ the notes were in the tag and commit messages (`git tag -n1`).
## Unreleased
## Unreleased
+## 0.73.0 — 2026-09-28
+
+**A person's own provider key lives in OpenVibe.AI** (roadmap WS-O task 2).
+- `ai.credential.manage` (first-party): the service that holds a person's consent (Live, for a streamer's AI viewers) stores their key at `PUT /api/v1/credentials/{subject}` (`ai.credential-put@1`: provider openai or anthropic, an https `base_url`, the key, models per role, and an optional `budget_usd_per_day`). It reads it back without the key (`ai.credential@1`, a four-character hint and today's spend) or deletes it. Only the storing service uses or changes a credential.
+- `ai.run-request@1` gains the optional `credential { subject }`. The run calls that provider with that key only: no fallback, never cached, the shared paid budget untouched, and the credential's own daily budget enforced. Chat operations only.
+
## 0.72.0 — 2026-09-27
## 0.72.0 — 2026-09-27
**Mod principals in Network** (roadmap WS-M task 3, ADR-013).
**Mod principals in Network** (roadmap WS-M task 3, ADR-013).
new file mode 100644
new file mode 100644
@@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential-put.v1.json",
+ "title": "AiCredentialPut",
+ "description": "ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.",
+ "type": "object",
+ "required": [
+ "provider",
+ "api_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "provider": {
+ "enum": [
+ "openai",
+ "anthropic"
+ ],
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ "base_url": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"
+ },
+ "api_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400
+ },
+ "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 Live role; `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 key; 0 or absent = no cap."
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential.v1.json",
+ "title": "AiCredential",
+ "description": "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.",
+ "type": "object",
+ "required": [
+ "subject",
+ "owner",
+ "provider",
+ "key_hint",
+ "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": [
+ "openai",
+ "anthropic"
+ ]
+ },
+ "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 Live role; `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"
+ }
+ }
+}
@@ -4,28 +4,69 @@
@@ -4,28 +4,69 @@
"title": "AiRunRequest",
"title": "AiRunRequest",
"description": "Body of POST /api/v1/runs on OpenVibe.AI (capability ai.run.create; ADR-015). Runs the newest active version of a workflow (or the given active or deprecated version) on input that must match that workflow version's own input schema; per-workflow input and output schemas live in AI's registry (GET /api/v1/workflows/:key), not here. The token's ns claim limits which workflow namespaces may run (403 capability.namespace_denied). ?wait=ms waits for the result: 201 finished or served from cache, 202 still queued/running (poll GET /api/v1/runs/:id), 200 an idempotent replay. Errors are problem+json: 404 workflow.not_found, 409 workflow.inactive, 409 idempotency.conflict, 413 input.too_large, 422 input.invalid, 429 quota.exceeded or queue.full with Retry-After. The direct operations POST /api/v1/{chat,generate,summarize,classify,extract,enrich,embed} take the same fields (except workflow and version) with the input fields at the top level and run workflow ai.<op>. target (EntityRef): what the output is about, part of the cache scope and a run filter. attribution (EntityRef): what the spend is attributed to for quotas and usage. on_behalf_of (SubjectRef): the person or actor the caller acts for, part of the cache scope and per-actor quotas.",
"description": "Body of POST /api/v1/runs on OpenVibe.AI (capability ai.run.create; ADR-015). Runs the newest active version of a workflow (or the given active or deprecated version) on input that must match that workflow version's own input schema; per-workflow input and output schemas live in AI's registry (GET /api/v1/workflows/:key), not here. The token's ns claim limits which workflow namespaces may run (403 capability.namespace_denied). ?wait=ms waits for the result: 201 finished or served from cache, 202 still queued/running (poll GET /api/v1/runs/:id), 200 an idempotent replay. Errors are problem+json: 404 workflow.not_found, 409 workflow.inactive, 409 idempotency.conflict, 413 input.too_large, 422 input.invalid, 429 quota.exceeded or queue.full with Retry-After. The direct operations POST /api/v1/{chat,generate,summarize,classify,extract,enrich,embed} take the same fields (except workflow and version) with the input fields at the top level and run workflow ai.<op>. target (EntityRef): what the output is about, part of the cache scope and a run filter. attribution (EntityRef): what the spend is attributed to for quotas and usage. on_behalf_of (SubjectRef): the person or actor the caller acts for, part of the cache scope and per-actor quotas.",
"type": "object",
"type": "object",
- "required": ["workflow"],
+ "required": [
+ "workflow"
+ ],
"additionalProperties": false,
"additionalProperties": false,
"properties": {
"properties": {
"workflow": {
"workflow": {
- "type": "string", "pattern": "^[a-z][a-z0-9_-]*(\\.[a-z0-9_-]+)+$", "maxLength": 200,
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_-]*(\\.[a-z0-9_-]+)+$",
+ "maxLength": 200,
"description": "Workflow key, <namespace>.<name> (live.chat_reply, news.summarize_story, network.site_copy…)."
"description": "Workflow key, <namespace>.<name> (live.chat_reply, news.summarize_story, network.site_copy…)."
},
},
- "version": { "type": "integer", "minimum": 1, "description": "Pin a workflow version (active or deprecated). Omitted: the newest active version." },
- "input": { "type": "object", "description": "Workflow input; validated against the workflow version's input_schema. Default {}." },
- "target": { "$ref": "../common/entity-ref.v1.json" },
- "attribution": { "$ref": "../common/entity-ref.v1.json" },
- "on_behalf_of": { "$ref": "../identity/subject-ref.v1.json" },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Pin a workflow version (active or deprecated). Omitted: the newest active version."
+ },
+ "input": {
+ "type": "object",
+ "description": "Workflow input; validated against the workflow version's input_schema. Default {}."
+ },
+ "target": {
+ "$ref": "../common/entity-ref.v1.json"
+ },
+ "attribution": {
+ "$ref": "../common/entity-ref.v1.json"
+ },
+ "on_behalf_of": {
+ "$ref": "../identity/subject-ref.v1.json"
+ },
"idempotency_key": {
"idempotency_key": {
- "type": "string", "pattern": "^[A-Za-z0-9._:-]{8,128}$",
+ "type": "string",
+ "pattern": "^[A-Za-z0-9._:-]{8,128}$",
"description": "Same (requester, key) returns the existing run; a different workflow or input under it is 409 idempotency.conflict. The Idempotency-Key header is used when this is absent."
"description": "Same (requester, key) returns the existing run; a different workflow or input under it is 409 idempotency.conflict. The Idempotency-Key header is used when this is absent."
},
},
"options": {
"options": {
- "type": "object", "additionalProperties": false,
+ "type": "object",
+ "additionalProperties": false,
"properties": {
"properties": {
- "cache": { "type": "boolean", "default": true, "description": "false skips the scoped cache lookup and store." },
- "debug": { "type": "boolean", "default": false, "description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on." }
+ "cache": {
+ "type": "boolean",
+ "default": true,
+ "description": "false skips the scoped cache lookup and store."
+ },
+ "debug": {
+ "type": "boolean",
+ "default": false,
+ "description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."
+ }
}
}
+ },
+ "credential": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "subject"
+ ],
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ },
+ "description": "Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision)."
}
}
}
}
}
}
@@ -1205,6 +1205,24 @@
@@ -1205,6 +1205,24 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "ai.credential-put",
+ "version": "1.0.0",
+ "owner": "ai",
+ "schema": "ai/credential-put.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "ai.credential",
+ "version": "1.0.0",
+ "owner": "ai",
+ "schema": "ai/credential.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
{
{
"id": "ai.run-request",
"id": "ai.run-request",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"openai","base_url":"http://10.0.0.1/v1","api_key":"sk-EXAMPLEEXAMPLE"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"provider":"openai","base_url":"https://openrouter.ai/api/v1","api_key":"sk-or-v1-EXAMPLEEXAMPLEEXAMPLE","models":{"chat":"gpt-4o-mini"},"budget_usd_per_day":2}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"live","provider":"openai","api_key":"sk-EXAMPLE","key_hint":"…MPLE","created_at":"2026-09-28T00:00:00.000Z","updated_at":"2026-09-28T00:00:00.000Z"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"live","provider":"openai","base_url":"https://openrouter.ai/api/v1","key_hint":"…MPLE","models":{"chat":"gpt-4o-mini"},"budget_usd_per_day":2,"spent_usd_today":0.12,"created_at":"2026-09-28T00:00:00.000Z","updated_at":"2026-09-28T00:00:00.000Z","last_used_at":null}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"workflow":"live.viewers.line","input":{"system":"s","user":"u"},"credential":{"subject":"usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"}}
@@ -11818,6 +11818,189 @@
@@ -11818,6 +11818,189 @@
}
}
}
}
},
},
+ "ai.credential-put": {
+ "version": "1.0.0",
+ "owner": "ai",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential-put.v1.json",
+ "title": "AiCredentialPut",
+ "description": "ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.",
+ "type": "object",
+ "required": [
+ "provider",
+ "api_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "provider": {
+ "enum": [
+ "openai",
+ "anthropic"
+ ],
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ "base_url": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"
+ },
+ "api_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400
+ },
+ "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 Live role; `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 key; 0 or absent = no cap."
+ }
+ }
+ }
+ },
+ "ai.credential": {
+ "version": "1.0.0",
+ "owner": "ai",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/credential.v1.json",
+ "title": "AiCredential",
+ "description": "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.",
+ "type": "object",
+ "required": [
+ "subject",
+ "owner",
+ "provider",
+ "key_hint",
+ "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": [
+ "openai",
+ "anthropic"
+ ]
+ },
+ "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 Live role; `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"
+ }
+ }
+ }
+ },
"ai.run-request": {
"ai.run-request": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "ai",
"owner": "ai",
@@ -11877,6 +12060,20 @@
@@ -11877,6 +12060,20 @@
"description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."
"description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."
}
}
}
}
+ },
+ "credential": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "subject"
+ ],
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ },
+ "description": "Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision)."
}
}
}
}
}
}
@@ -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.72.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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"
@@ -267,6 +267,354 @@
@@ -267,6 +267,354 @@
}
}
}
}
},
},
+ "/api/v1/credentials/{subject}": {
+ "delete": {
+ "operationId": "delete_api_v1_credentials_subject",
+ "summary": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential).",
+ "description": "**ai.credential.manage** (first-party): Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",
+ "tags": [
+ "ai.credential"
+ ],
+ "x-openvibe-capabilities": [
+ "ai.credential.manage"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "ai-credentials",
+ "security": [
+ {
+ "openvibeToken": [
+ "ai.credential.manage"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/ai.credential-put.v1"
+ },
+ "parameters": [
+ {
+ "name": "subject",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "provider",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "enum": [
+ "openai",
+ "anthropic"
+ ],
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ {
+ "name": "base_url",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"
+ }
+ },
+ {
+ "name": "api_key",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400
+ }
+ },
+ {
+ "name": "models",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "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 Live role; `chat` is the default for the others."
+ },
+ "description": "Model per Live role; `chat` is the default for the others."
+ },
+ {
+ "name": "budget_usd_per_day",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 1000,
+ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."
+ },
+ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.credential.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "get": {
+ "operationId": "get_api_v1_credentials_subject",
+ "summary": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential).",
+ "description": "**ai.credential.manage** (first-party): Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",
+ "tags": [
+ "ai.credential"
+ ],
+ "x-openvibe-capabilities": [
+ "ai.credential.manage"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "ai-credentials",
+ "security": [
+ {
+ "openvibeToken": [
+ "ai.credential.manage"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/ai.credential-put.v1"
+ },
+ "parameters": [
+ {
+ "name": "subject",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "provider",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "enum": [
+ "openai",
+ "anthropic"
+ ],
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ {
+ "name": "base_url",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"
+ }
+ },
+ {
+ "name": "api_key",
+ "in": "query",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400
+ }
+ },
+ {
+ "name": "models",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "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 Live role; `chat` is the default for the others."
+ },
+ "description": "Model per Live role; `chat` is the default for the others."
+ },
+ {
+ "name": "budget_usd_per_day",
+ "in": "query",
+ "required": false,
+ "schema": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 1000,
+ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."
+ },
+ "description": "The person's own daily cap on estimated spend with this key; 0 or absent = no cap."
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.credential.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "operationId": "put_api_v1_credentials_subject",
+ "summary": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential).",
+ "description": "**ai.credential.manage** (first-party): Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",
+ "tags": [
+ "ai.credential"
+ ],
+ "x-openvibe-capabilities": [
+ "ai.credential.manage"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "ai-credentials",
+ "security": [
+ {
+ "openvibeToken": [
+ "ai.credential.manage"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.credential-put.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "subject",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.credential.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v1/embed": {
"/api/v1/embed": {
"post": {
"post": {
"operationId": "post_api_v1_embed",
"operationId": "post_api_v1_embed",
@@ -2154,6 +2502,175 @@
@@ -2154,6 +2502,175 @@
},
},
"components": {
"components": {
"schemas": {
"schemas": {
+ "ai.credential-put.v1": {
+ "title": "AiCredentialPut",
+ "description": "ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.",
+ "type": "object",
+ "required": [
+ "provider",
+ "api_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "provider": {
+ "enum": [
+ "openai",
+ "anthropic"
+ ],
+ "description": "openai = any OpenAI-compatible endpoint."
+ },
+ "base_url": {
+ "type": "string",
+ "maxLength": 300,
+ "pattern": "^https://[^\\s/?#@]+(/[^\\s?#]*)?$"
+ },
+ "api_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 400
+ },
+ "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 Live role; `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 key; 0 or absent = no cap."
+ }
+ }
+ },
+ "ai.credential.v1": {
+ "title": "AiCredential",
+ "description": "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.",
+ "type": "object",
+ "required": [
+ "subject",
+ "owner",
+ "provider",
+ "key_hint",
+ "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": [
+ "openai",
+ "anthropic"
+ ]
+ },
+ "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 Live role; `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"
+ }
+ }
+ },
"ai.definition-version-request.v1": {
"ai.definition-version-request.v1": {
"title": "AiDefinitionVersionRequest",
"title": "AiDefinitionVersionRequest",
"description": "ai.definition-version-request@1: bodies of ai.workflow.manage on OpenVibe.AI. An edit is always a new version (the previous one stays readable); fields left out are taken from the newest existing version. POST /api/v1/templates/:key/versions: a prompt template (input_schema and output_schema must compile as JSON Schema; visibility public, first-party or internal). POST /api/v1/workflows/:key/versions (key <namespace>.<name>): steps (at least one; kind llm (naming an existing template), passthrough, transcribe or embed), schemas, default route, cache mode. POST /api/v1/routes/:key/versions: primary { provider, model } and fallbacks (every provider must exist), or alias_of another route. POST …/:key/versions/:version/status: { status } (templates and workflows draft|active|deprecated|archived; routes active|disabled). Refusals are 422 ai.invalid.",
"description": "ai.definition-version-request@1: bodies of ai.workflow.manage on OpenVibe.AI. An edit is always a new version (the previous one stays readable); fields left out are taken from the newest existing version. POST /api/v1/templates/:key/versions: a prompt template (input_schema and output_schema must compile as JSON Schema; visibility public, first-party or internal). POST /api/v1/workflows/:key/versions (key <namespace>.<name>): steps (at least one; kind llm (naming an existing template), passthrough, transcribe or embed), schemas, default route, cache mode. POST /api/v1/routes/:key/versions: primary { provider, model } and fallbacks (every provider must exist), or alias_of another route. POST …/:key/versions/:version/status: { status } (templates and workflows draft|active|deprecated|archived; routes active|disabled). Refusals are 422 ai.invalid.",
@@ -3469,6 +3986,20 @@
@@ -3469,6 +3986,20 @@
"description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."
"description": "Keep raw prompts and responses in the request log, only when AI runs with raw debug logging on."
}
}
}
}
+ },
+ "credential": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "subject"
+ ],
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ },
+ "description": "Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision)."
}
}
}
}
},
},
@@ -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.72.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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"
@@ -5,8 +5,8 @@
@@ -5,8 +5,8 @@
"service": "ai",
"service": "ai",
"name": "OpenVibe.AI",
"name": "OpenVibe.AI",
"origin": "https://ai.openvibe.network",
"origin": "https://ai.openvibe.network",
- "operations": 37,
- "capabilities": 5
+ "operations": 40,
+ "capabilities": 6
},
},
{
{
"service": "billing",
"service": "billing",
@@ -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.72.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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": "OpenRe.Stream API",
"title": "OpenRe.Stream API",
- "version": "0.72.0",
- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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.72.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for 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.73.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.73.0): each operation lists the capabilities it performs; a token for 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"
@@ -15769,6 +15769,63 @@ export interface BlogThemeRequest {
@@ -15769,6 +15769,63 @@ export interface BlogThemeRequest {
theme: "vibe" | "paper" | "slate" | "sand" | "nord" | "high-contrast";
theme: "vibe" | "paper" | "slate" | "sand" | "nord" | "high-contrast";
}
}
+/** [email protected] (owner: ai) */
+/**
+ * ai.credential-put@1 (OpenVibe.AI; roadmap WS-O task 2): a person's own provider key, stored by the service that holds their consent (Live, for a streamer's AI viewers), PUT /api/v1/credentials/{subject} with capability ai.credential.manage. OpenVibe.AI encrypts the key at rest and never returns it; runs that name the credential call that provider with it, never a shared key, and are limited by `budget_usd_per_day`. `base_url` is any https endpoint (OpenAI-compatible or Anthropic); OpenVibe.AI connects only to public addresses.
+ */
+export interface AiCredentialPut {
+ /**
+ * openai = any OpenAI-compatible endpoint.
+ */
+ provider: "openai" | "anthropic";
+ base_url?: string;
+ api_key: string;
+ /**
+ * Model per Live role; `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 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.
+ */
+export interface AiCredential {
+ subject: string;
+ /**
+ * The service that stored it; only it may use or change it.
+ */
+ owner: string;
+ provider: "openai" | "anthropic";
+ base_url?: string | null;
+ key_hint: string;
+ /**
+ * Model per Live role; `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) */
/**
/**
* Body of POST /api/v1/runs on OpenVibe.AI (capability ai.run.create; ADR-015). Runs the newest active version of a workflow (or the given active or deprecated version) on input that must match that workflow version's own input schema; per-workflow input and output schemas live in AI's registry (GET /api/v1/workflows/:key), not here. The token's ns claim limits which workflow namespaces may run (403 capability.namespace_denied). ?wait=ms waits for the result: 201 finished or served from cache, 202 still queued/running (poll GET /api/v1/runs/:id), 200 an idempotent replay. Errors are problem+json: 404 workflow.not_found, 409 workflow.inactive, 409 idempotency.conflict, 413 input.too_large, 422 input.invalid, 429 quota.exceeded or queue.full with Retry-After. The direct operations POST /api/v1/{chat,generate,summarize,classify,extract,enrich,embed} take the same fields (except workflow and version) with the input fields at the top level and run workflow ai.<op>. target (EntityRef): what the output is about, part of the cache scope and a run filter. attribution (EntityRef): what the spend is attributed to for quotas and usage. on_behalf_of (SubjectRef): the person or actor the caller acts for, part of the cache scope and per-actor quotas.
* Body of POST /api/v1/runs on OpenVibe.AI (capability ai.run.create; ADR-015). Runs the newest active version of a workflow (or the given active or deprecated version) on input that must match that workflow version's own input schema; per-workflow input and output schemas live in AI's registry (GET /api/v1/workflows/:key), not here. The token's ns claim limits which workflow namespaces may run (403 capability.namespace_denied). ?wait=ms waits for the result: 201 finished or served from cache, 202 still queued/running (poll GET /api/v1/runs/:id), 200 an idempotent replay. Errors are problem+json: 404 workflow.not_found, 409 workflow.inactive, 409 idempotency.conflict, 413 input.too_large, 422 input.invalid, 429 quota.exceeded or queue.full with Retry-After. The direct operations POST /api/v1/{chat,generate,summarize,classify,extract,enrich,embed} take the same fields (except workflow and version) with the input fields at the top level and run workflow ai.<op>. target (EntityRef): what the output is about, part of the cache scope and a run filter. attribution (EntityRef): what the spend is attributed to for quotas and usage. on_behalf_of (SubjectRef): the person or actor the caller acts for, part of the cache scope and per-actor quotas.
@@ -15803,6 +15860,12 @@ export interface AiRunRequest {
@@ -15803,6 +15860,12 @@ export interface AiRunRequest {
*/
*/
debug?: boolean;
debug?: boolean;
};
};
+ /**
+ * Run with the person's own provider key (ai.credential@1) that this service stored, instead of a shared route: only that provider is called (no fallback), the result is never cached or taken from the cache, the shared paid budget is not spent, and the credential's own daily budget applies (429 quota.exceeded). Chat operations only (text, JSON, vision).
+ */
+ credential?: {
+ subject: string;
+ };
}
}
/** [email protected] (owner: ai) */
/** [email protected] (owner: ai) */
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "id": "ai.credential.manage",
+ "version": "1.0",
+ "owner": "ai",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Store, read (never the key) or delete a person's own provider key, for runs made on their behalf with it (ai.run-request credential). Only the service that stored a credential reads, uses or changes it.",
+ "permissions": [
+ "ai:credentials"
+ ],
+ "resourceConstraints": [
+ "owner"
+ ],
+ "quotaClass": "ai-credentials",
+ "events": [],
+ "implementedBy": [
+ "PUT /api/v1/credentials/:subject",
+ "GET /api/v1/credentials/:subject",
+ "DELETE /api/v1/credentials/:subject"
+ ],
+ "inputSchema": "ai.credential-put@1",
+ "outputSchema": "ai.credential@1"
+}
@@ -20,11 +20,12 @@
@@ -20,11 +20,12 @@
"note": "called by other services at 127.0.0.1:4700; ai.openvibe.network serves the OpenVibe.Sites placeholder page"
"note": "called by other services at 127.0.0.1:4700; ai.openvibe.network serves the OpenVibe.Sites placeholder page"
},
},
"capabilities": [
"capabilities": [
+ "ai.credential.manage",
+ "ai.provider.manage",
"ai.run.create",
"ai.run.create",
"ai.run.read",
"ai.run.read",
- "ai.workflow.manage",
- "ai.provider.manage",
- "ai.usage.read"
+ "ai.usage.read",
+ "ai.workflow.manage"
],
],
"eventsProduced": [
"eventsProduced": [
"ai.run.queued",
"ai.run.queued",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.72.0",
+ "version": "0.73.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",