openvibers/openvibe.contracts Commits
v0.75.0: per-streamer AI budgets are AI quotas (roadmap WS-O task 2). ai.quota.attribution.manage (first-party): a service caps what runs attributed to one of its own entities may cost or request per hour or day (PUT /api/v1/attribution-quotas/{attribution}, ai.attribution-quota-put@1, optionally for a workflow prefix), reads it with the window's use (ai.attribution-quota@1) or removes it; the attribution's service must be the caller (Live: live:user:<id>). Over the cap a run is refused 429 quota.exceeded before any provider is called.
Changes
@@@ -6,6 +6,11 @@ the notes were in the tag and commit messages (`git tag -n1`).## Unreleased++## 0.75.0 — 2026-09-28++++**Per-streamer AI budgets are AI quotas** (roadmap WS-O task 2).++- `ai.quota.attribution.manage` (first-party): a service caps what runs attributed to one of its own entities may cost or request per hour or day (`PUT /api/v1/attribution-quotas/{attribution}`, `ai.attribution-quota-put@1`, optionally only for workflows under a prefix). It reads the cap with what the window has used (`ai.attribution-quota@1`) or removes it. The attribution's service must be the caller: Live caps `live:user:<id>`, a streamer's daily AI-viewer budget. A run over the cap is refused 429 `quota.exceeded` before any provider is called.++## 0.74.0 — 2026-09-28- `ai.credential-put@1`: `api_key` is optional after the first put. The stored key is kept for a change of models or budget, but must be entered again to change `provider` or `base_url`, so a key never follows a new endpoint on its own (400 `credential.key_required` otherwise). Roadmap WS-O task 2.nnew file mode 100644@@@ -0,0 +1,46 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/attribution-quota-put.v1.json",++ "title": "AiAttributionQuotaPut",++ "description": "ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.",++ "type": "object",++ "required": [++ "window"++ ],++ "additionalProperties": false,++ "properties": {++ "window": {++ "enum": [++ "hour",++ "day"++ ]++ },++ "max_cost_usd": {++ "type": "number",++ "minimum": 0,++ "maximum": 10000++ },++ "max_requests": {++ "type": "integer",++ "minimum": 0,++ "maximum": 1000000++ },++ "workflow_prefix": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_.-]{1,79}$",++ "description": "Only runs of workflows whose key starts with this (live.viewers.)."++ }++ },++ "anyOf": [++ {++ "required": [++ "max_cost_usd"++ ]++ },++ {++ "required": [++ "max_requests"++ ]++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,74 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/attribution-quota.v1.json",++ "title": "AiAttributionQuota",++ "description": "ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.",++ "type": "object",++ "required": [++ "attribution",++ "window",++ "used",++ "window_resets_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "attribution": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{1,31}:[a-z][a-z0-9_]{1,31}:[A-Za-z0-9_.-]{1,80}$",++ "description": "<service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>)."++ },++ "window": {++ "enum": [++ "hour",++ "day"++ ]++ },++ "workflow_prefix": {++ "type": [++ "string",++ "null"++ ]++ },++ "max_cost_usd": {++ "type": [++ "number",++ "null"++ ],++ "minimum": 0++ },++ "max_requests": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 0++ },++ "used": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "requests",++ "cost_usd"++ ],++ "properties": {++ "requests": {++ "type": "integer",++ "minimum": 0++ },++ "cost_usd": {++ "type": "number",++ "minimum": 0++ }++ }++ },++ "window_resets_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ }++ }++}@@@ -1223,6 +1223,24 @@"compatibility": "backward","status": "active"},++ {++ "id": "ai.attribution-quota-put",++ "version": "1.0.0",++ "owner": "ai",++ "schema": "ai/attribution-quota-put.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },++ {++ "id": "ai.attribution-quota",++ "version": "1.0.0",++ "owner": "ai",++ "schema": "ai/attribution-quota.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active"++ },{"id": "ai.run-request","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1 @@++{"window":"minute","max_requests":5}nnew file mode 100644@@@ -0,0 +1 @@++{"window":"day"}nnew file mode 100644@@@ -0,0 +1 @@++{"window":"day","max_cost_usd":0.2,"workflow_prefix":"live.viewers."}nnew file mode 100644@@@ -0,0 +1 @@++{"attribution":"42","window":"day","used":{"requests":0,"cost_usd":0},"window_resets_at":"2026-09-29T00:00:00.000Z","updated_at":"2026-09-28T00:30:00.000Z"}nnew file mode 100644@@@ -0,0 +1 @@++{"attribution":"live:user:42","window":"day","workflow_prefix":"live.viewers.","max_cost_usd":0.2,"max_requests":null,"used":{"requests":12,"cost_usd":0.034},"window_resets_at":"2026-09-29T00:00:00.000Z","updated_at":"2026-09-28T00:30:00.000Z"}@@@ -12001,6 +12001,136 @@}}},++ "ai.attribution-quota-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/attribution-quota-put.v1.json",++ "title": "AiAttributionQuotaPut",++ "description": "ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.",++ "type": "object",++ "required": [++ "window"++ ],++ "additionalProperties": false,++ "properties": {++ "window": {++ "enum": [++ "hour",++ "day"++ ]++ },++ "max_cost_usd": {++ "type": "number",++ "minimum": 0,++ "maximum": 10000++ },++ "max_requests": {++ "type": "integer",++ "minimum": 0,++ "maximum": 1000000++ },++ "workflow_prefix": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_.-]{1,79}$",++ "description": "Only runs of workflows whose key starts with this (live.viewers.)."++ }++ },++ "anyOf": [++ {++ "required": [++ "max_cost_usd"++ ]++ },++ {++ "required": [++ "max_requests"++ ]++ }++ ]++ }++ },++ "ai.attribution-quota": {++ "version": "1.0.0",++ "owner": "ai",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/ai/attribution-quota.v1.json",++ "title": "AiAttributionQuota",++ "description": "ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.",++ "type": "object",++ "required": [++ "attribution",++ "window",++ "used",++ "window_resets_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "attribution": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{1,31}:[a-z][a-z0-9_]{1,31}:[A-Za-z0-9_.-]{1,80}$",++ "description": "<service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>)."++ },++ "window": {++ "enum": [++ "hour",++ "day"++ ]++ },++ "workflow_prefix": {++ "type": [++ "string",++ "null"++ ]++ },++ "max_cost_usd": {++ "type": [++ "number",++ "null"++ ],++ "minimum": 0++ },++ "max_requests": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 0++ },++ "used": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "requests",++ "cost_usd"++ ],++ "properties": {++ "requests": {++ "type": "integer",++ "minimum": 0++ },++ "cost_usd": {++ "type": "number",++ "minimum": 0++ }++ }++ },++ "window_resets_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ },"ai.run-request": {"version": "1.0.0","owner": "ai",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.74.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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"@@@ -16,6 +16,186 @@}],"paths": {++ "/api/v1/attribution-quotas/{attribution}": {++ "delete": {++ "operationId": "delete_api_v1_attribution_quotas_attribution",++ "summary": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live).",++ "description": "**ai.quota.attribution.manage** (first-party): Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",++ "tags": [++ "ai.quota"++ ],++ "x-openvibe-capabilities": [++ "ai.quota.attribution.manage"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "ai-quotas",++ "security": [++ {++ "openvibeToken": [++ "ai.quota.attribution.manage"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/ai.attribution-quota-put.v1"++ },++ "parameters": [++ {++ "name": "attribution",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.attribution-quota.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_attribution_quotas_attribution",++ "summary": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live).",++ "description": "**ai.quota.attribution.manage** (first-party): Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",++ "tags": [++ "ai.quota"++ ],++ "x-openvibe-capabilities": [++ "ai.quota.attribution.manage"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "ai-quotas",++ "security": [++ {++ "openvibeToken": [++ "ai.quota.attribution.manage"++ ]++ }++ ],++ "x-openvibe-input": {++ "$ref": "#/components/schemas/ai.attribution-quota-put.v1"++ },++ "parameters": [++ {++ "name": "attribution",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.attribution-quota.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_attribution_quotas_attribution",++ "summary": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live).",++ "description": "**ai.quota.attribution.manage** (first-party): Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",++ "tags": [++ "ai.quota"++ ],++ "x-openvibe-capabilities": [++ "ai.quota.attribution.manage"++ ],++ "x-openvibe-visibility": [++ "first-party"++ ],++ "x-openvibe-quota-class": "ai-quotas",++ "security": [++ {++ "openvibeToken": [++ "ai.quota.attribution.manage"++ ]++ }++ ],++ "requestBody": {++ "required": false,++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.attribution-quota-put.v1"++ }++ }++ }++ },++ "parameters": [++ {++ "name": "attribution",++ "in": "path",++ "required": true,++ "schema": {++ "type": "string"++ }++ }++ ],++ "responses": {++ "2XX": {++ "description": "Success",++ "content": {++ "application/json": {++ "schema": {++ "$ref": "#/components/schemas/ai.attribution-quota.v1"++ }++ }++ }++ },++ "default": {++ "description": "An error (RFC 9457 problem details)",++ "content": {++ "application/problem+json": {++ "schema": {++ "$ref": "#/components/schemas/errors.problem.v1"++ }++ }++ }++ }++ }++ }++ },"/api/v1/audit": {"get": {"operationId": "get_api_v1_audit",@@@ -2506,6 +2686,122 @@},"components": {"schemas": {++ "ai.attribution-quota-put.v1": {++ "title": "AiAttributionQuotaPut",++ "description": "ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.",++ "type": "object",++ "required": [++ "window"++ ],++ "additionalProperties": false,++ "properties": {++ "window": {++ "enum": [++ "hour",++ "day"++ ]++ },++ "max_cost_usd": {++ "type": "number",++ "minimum": 0,++ "maximum": 10000++ },++ "max_requests": {++ "type": "integer",++ "minimum": 0,++ "maximum": 1000000++ },++ "workflow_prefix": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_.-]{1,79}$",++ "description": "Only runs of workflows whose key starts with this (live.viewers.)."++ }++ },++ "anyOf": [++ {++ "required": [++ "max_cost_usd"++ ]++ },++ {++ "required": [++ "max_requests"++ ]++ }++ ]++ },++ "ai.attribution-quota.v1": {++ "title": "AiAttributionQuota",++ "description": "ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.",++ "type": "object",++ "required": [++ "attribution",++ "window",++ "used",++ "window_resets_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "attribution": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9-]{1,31}:[a-z][a-z0-9_]{1,31}:[A-Za-z0-9_.-]{1,80}$",++ "description": "<service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>)."++ },++ "window": {++ "enum": [++ "hour",++ "day"++ ]++ },++ "workflow_prefix": {++ "type": [++ "string",++ "null"++ ]++ },++ "max_cost_usd": {++ "type": [++ "number",++ "null"++ ],++ "minimum": 0++ },++ "max_requests": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 0++ },++ "used": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "requests",++ "cost_usd"++ ],++ "properties": {++ "requests": {++ "type": "integer",++ "minimum": 0++ },++ "cost_usd": {++ "type": "number",++ "minimum": 0++ }++ }++ },++ "window_resets_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ }++ }++ },"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.",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.74.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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": 40,-- "capabilities": 6++ "operations": 43,++ "capabilities": 7},{"service": "billing",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.74.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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"@@@ -15829,6 +15829,43 @@ export interface AiCredential {last_used_at?: string | null;}++/** [email protected] (owner: ai) */++/**++ * ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.++ */++export type AiAttributionQuotaPut = {++ [k: string]: unknown | undefined;++} & {++ window: "hour" | "day";++ max_cost_usd?: number;++ max_requests?: number;++ /**++ * Only runs of workflows whose key starts with this (live.viewers.).++ */++ workflow_prefix?: string;++};++++/** [email protected] (owner: ai) */++/**++ * ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.++ */++export interface AiAttributionQuota {++ /**++ * <service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>).++ */++ attribution: string;++ window: "hour" | "day";++ workflow_prefix?: string | null;++ max_cost_usd?: number | null;++ max_requests?: number | null;++ used: {++ requests: number;++ cost_usd: number;++ };++ window_resets_at: string;++ updated_at: string;++}++/** [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.nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "id": "ai.quota.attribution.manage",++ "version": "1.0",++ "owner": "ai",++ "status": "active",++ "visibility": "first-party",++ "description": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",++ "permissions": [++ "ai:quotas"++ ],++ "resourceConstraints": [++ "owner"++ ],++ "quotaClass": "ai-quotas",++ "events": [],++ "implementedBy": [++ "PUT /api/v1/attribution-quotas/:attribution",++ "GET /api/v1/attribution-quotas/:attribution",++ "DELETE /api/v1/attribution-quotas/:attribution"++ ],++ "inputSchema": "ai.attribution-quota-put@1",++ "outputSchema": "ai.attribution-quota@1"++}@@@ -22,6 +22,7 @@"capabilities": ["ai.credential.manage","ai.provider.manage",++ "ai.quota.attribution.manage","ai.run.create","ai.run.read","ai.usage.read",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.74.0",++ "version": "0.75.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,11 @@ the notes were in the tag and commit messages (`git tag -n1`).
@@ -6,6 +6,11 @@ the notes were in the tag and commit messages (`git tag -n1`).
## Unreleased
## Unreleased
+## 0.75.0 — 2026-09-28
+
+**Per-streamer AI budgets are AI quotas** (roadmap WS-O task 2).
+- `ai.quota.attribution.manage` (first-party): a service caps what runs attributed to one of its own entities may cost or request per hour or day (`PUT /api/v1/attribution-quotas/{attribution}`, `ai.attribution-quota-put@1`, optionally only for workflows under a prefix). It reads the cap with what the window has used (`ai.attribution-quota@1`) or removes it. The attribution's service must be the caller: Live caps `live:user:<id>`, a streamer's daily AI-viewer budget. A run over the cap is refused 429 `quota.exceeded` before any provider is called.
+
## 0.74.0 — 2026-09-28
## 0.74.0 — 2026-09-28
- `ai.credential-put@1`: `api_key` is optional after the first put. The stored key is kept for a change of models or budget, but must be entered again to change `provider` or `base_url`, so a key never follows a new endpoint on its own (400 `credential.key_required` otherwise). Roadmap WS-O task 2.
- `ai.credential-put@1`: `api_key` is optional after the first put. The stored key is kept for a change of models or budget, but must be entered again to change `provider` or `base_url`, so a key never follows a new endpoint on its own (400 `credential.key_required` otherwise). Roadmap WS-O task 2.
new file mode 100644
new file mode 100644
@@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/attribution-quota-put.v1.json",
+ "title": "AiAttributionQuotaPut",
+ "description": "ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.",
+ "type": "object",
+ "required": [
+ "window"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ]
+ },
+ "max_cost_usd": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 10000
+ },
+ "max_requests": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "workflow_prefix": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_.-]{1,79}$",
+ "description": "Only runs of workflows whose key starts with this (live.viewers.)."
+ }
+ },
+ "anyOf": [
+ {
+ "required": [
+ "max_cost_usd"
+ ]
+ },
+ {
+ "required": [
+ "max_requests"
+ ]
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/attribution-quota.v1.json",
+ "title": "AiAttributionQuota",
+ "description": "ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.",
+ "type": "object",
+ "required": [
+ "attribution",
+ "window",
+ "used",
+ "window_resets_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "attribution": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{1,31}:[a-z][a-z0-9_]{1,31}:[A-Za-z0-9_.-]{1,80}$",
+ "description": "<service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>)."
+ },
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ]
+ },
+ "workflow_prefix": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "max_cost_usd": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "max_requests": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "used": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "requests",
+ "cost_usd"
+ ],
+ "properties": {
+ "requests": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cost_usd": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "window_resets_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+}
@@ -1223,6 +1223,24 @@
@@ -1223,6 +1223,24 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "ai.attribution-quota-put",
+ "version": "1.0.0",
+ "owner": "ai",
+ "schema": "ai/attribution-quota-put.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active"
+ },
+ {
+ "id": "ai.attribution-quota",
+ "version": "1.0.0",
+ "owner": "ai",
+ "schema": "ai/attribution-quota.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 @@
+{"window":"minute","max_requests":5}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"window":"day"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"window":"day","max_cost_usd":0.2,"workflow_prefix":"live.viewers."}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"attribution":"42","window":"day","used":{"requests":0,"cost_usd":0},"window_resets_at":"2026-09-29T00:00:00.000Z","updated_at":"2026-09-28T00:30:00.000Z"}
new file mode 100644
new file mode 100644
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+{"attribution":"live:user:42","window":"day","workflow_prefix":"live.viewers.","max_cost_usd":0.2,"max_requests":null,"used":{"requests":12,"cost_usd":0.034},"window_resets_at":"2026-09-29T00:00:00.000Z","updated_at":"2026-09-28T00:30:00.000Z"}
@@ -12001,6 +12001,136 @@
@@ -12001,6 +12001,136 @@
}
}
}
}
},
},
+ "ai.attribution-quota-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/attribution-quota-put.v1.json",
+ "title": "AiAttributionQuotaPut",
+ "description": "ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.",
+ "type": "object",
+ "required": [
+ "window"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ]
+ },
+ "max_cost_usd": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 10000
+ },
+ "max_requests": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "workflow_prefix": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_.-]{1,79}$",
+ "description": "Only runs of workflows whose key starts with this (live.viewers.)."
+ }
+ },
+ "anyOf": [
+ {
+ "required": [
+ "max_cost_usd"
+ ]
+ },
+ {
+ "required": [
+ "max_requests"
+ ]
+ }
+ ]
+ }
+ },
+ "ai.attribution-quota": {
+ "version": "1.0.0",
+ "owner": "ai",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/ai/attribution-quota.v1.json",
+ "title": "AiAttributionQuota",
+ "description": "ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.",
+ "type": "object",
+ "required": [
+ "attribution",
+ "window",
+ "used",
+ "window_resets_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "attribution": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{1,31}:[a-z][a-z0-9_]{1,31}:[A-Za-z0-9_.-]{1,80}$",
+ "description": "<service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>)."
+ },
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ]
+ },
+ "workflow_prefix": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "max_cost_usd": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "max_requests": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "used": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "requests",
+ "cost_usd"
+ ],
+ "properties": {
+ "requests": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cost_usd": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "window_resets_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ },
"ai.run-request": {
"ai.run-request": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "ai",
"owner": "ai",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.74.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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"
@@ -16,6 +16,186 @@
@@ -16,6 +16,186 @@
}
}
],
],
"paths": {
"paths": {
+ "/api/v1/attribution-quotas/{attribution}": {
+ "delete": {
+ "operationId": "delete_api_v1_attribution_quotas_attribution",
+ "summary": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live).",
+ "description": "**ai.quota.attribution.manage** (first-party): Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",
+ "tags": [
+ "ai.quota"
+ ],
+ "x-openvibe-capabilities": [
+ "ai.quota.attribution.manage"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "ai-quotas",
+ "security": [
+ {
+ "openvibeToken": [
+ "ai.quota.attribution.manage"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/ai.attribution-quota-put.v1"
+ },
+ "parameters": [
+ {
+ "name": "attribution",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.attribution-quota.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_attribution_quotas_attribution",
+ "summary": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live).",
+ "description": "**ai.quota.attribution.manage** (first-party): Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",
+ "tags": [
+ "ai.quota"
+ ],
+ "x-openvibe-capabilities": [
+ "ai.quota.attribution.manage"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "ai-quotas",
+ "security": [
+ {
+ "openvibeToken": [
+ "ai.quota.attribution.manage"
+ ]
+ }
+ ],
+ "x-openvibe-input": {
+ "$ref": "#/components/schemas/ai.attribution-quota-put.v1"
+ },
+ "parameters": [
+ {
+ "name": "attribution",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.attribution-quota.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_attribution_quotas_attribution",
+ "summary": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live).",
+ "description": "**ai.quota.attribution.manage** (first-party): Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",
+ "tags": [
+ "ai.quota"
+ ],
+ "x-openvibe-capabilities": [
+ "ai.quota.attribution.manage"
+ ],
+ "x-openvibe-visibility": [
+ "first-party"
+ ],
+ "x-openvibe-quota-class": "ai-quotas",
+ "security": [
+ {
+ "openvibeToken": [
+ "ai.quota.attribution.manage"
+ ]
+ }
+ ],
+ "requestBody": {
+ "required": false,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.attribution-quota-put.v1"
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "attribution",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "2XX": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ai.attribution-quota.v1"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "An error (RFC 9457 problem details)",
+ "content": {
+ "application/problem+json": {
+ "schema": {
+ "$ref": "#/components/schemas/errors.problem.v1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v1/audit": {
"/api/v1/audit": {
"get": {
"get": {
"operationId": "get_api_v1_audit",
"operationId": "get_api_v1_audit",
@@ -2506,6 +2686,122 @@
@@ -2506,6 +2686,122 @@
},
},
"components": {
"components": {
"schemas": {
"schemas": {
+ "ai.attribution-quota-put.v1": {
+ "title": "AiAttributionQuotaPut",
+ "description": "ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.",
+ "type": "object",
+ "required": [
+ "window"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ]
+ },
+ "max_cost_usd": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 10000
+ },
+ "max_requests": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 1000000
+ },
+ "workflow_prefix": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_.-]{1,79}$",
+ "description": "Only runs of workflows whose key starts with this (live.viewers.)."
+ }
+ },
+ "anyOf": [
+ {
+ "required": [
+ "max_cost_usd"
+ ]
+ },
+ {
+ "required": [
+ "max_requests"
+ ]
+ }
+ ]
+ },
+ "ai.attribution-quota.v1": {
+ "title": "AiAttributionQuota",
+ "description": "ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.",
+ "type": "object",
+ "required": [
+ "attribution",
+ "window",
+ "used",
+ "window_resets_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "attribution": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9-]{1,31}:[a-z][a-z0-9_]{1,31}:[A-Za-z0-9_.-]{1,80}$",
+ "description": "<service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>)."
+ },
+ "window": {
+ "enum": [
+ "hour",
+ "day"
+ ]
+ },
+ "workflow_prefix": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "max_cost_usd": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "max_requests": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "used": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "requests",
+ "cost_usd"
+ ],
+ "properties": {
+ "requests": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "cost_usd": {
+ "type": "number",
+ "minimum": 0
+ }
+ }
+ },
+ "window_resets_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
"ai.credential-put.v1": {
"ai.credential-put.v1": {
"title": "AiCredentialPut",
"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.",
"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.",
@@ -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.74.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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": 40,
- "capabilities": 6
+ "operations": 43,
+ "capabilities": 7
},
},
{
{
"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.74.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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.74.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.74.0): each operation lists the capabilities it performs; a token for 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.75.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.75.0): each operation lists the capabilities it performs; a token for 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"
@@ -15829,6 +15829,43 @@ export interface AiCredential {
@@ -15829,6 +15829,43 @@ export interface AiCredential {
last_used_at?: string | null;
last_used_at?: string | null;
}
}
+/** [email protected] (owner: ai) */
+/**
+ * ai.attribution-quota-put@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on runs attributed to one of the caller's own entities, PUT /api/v1/attribution-quotas/{attribution} with capability ai.quota.attribution.manage; the attribution's service must be the caller (Live caps live:user:<id>, a streamer's AI viewers). Over the cap a run is refused 429 quota.exceeded before any provider is called. Cost counts what runs have cost so far in the window, so the run that crosses the cap finishes and the next is refused.
+ */
+export type AiAttributionQuotaPut = {
+ [k: string]: unknown | undefined;
+} & {
+ window: "hour" | "day";
+ max_cost_usd?: number;
+ max_requests?: number;
+ /**
+ * Only runs of workflows whose key starts with this (live.viewers.).
+ */
+ workflow_prefix?: string;
+};
+
+/** [email protected] (owner: ai) */
+/**
+ * ai.attribution-quota@1 (OpenVibe.AI; roadmap WS-O task 2): a cap on one attribution as its service reads it (GET or PUT /api/v1/attribution-quotas/{attribution}), with what the current window has used.
+ */
+export interface AiAttributionQuota {
+ /**
+ * <service>:<type>:<id>, the run's attribution as AI keys it (Live: live:user:<id>).
+ */
+ attribution: string;
+ window: "hour" | "day";
+ workflow_prefix?: string | null;
+ max_cost_usd?: number | null;
+ max_requests?: number | null;
+ used: {
+ requests: number;
+ cost_usd: number;
+ };
+ window_resets_at: string;
+ updated_at: string;
+}
+
/** [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.
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "id": "ai.quota.attribution.manage",
+ "version": "1.0",
+ "owner": "ai",
+ "status": "active",
+ "visibility": "first-party",
+ "description": "Cap what runs attributed to one of the caller's own entities may cost or request per hour or day (a streamer's daily AI budget on Live). Only the service named in the attribution sets, reads or removes its caps; a run over a cap is refused before any provider is called.",
+ "permissions": [
+ "ai:quotas"
+ ],
+ "resourceConstraints": [
+ "owner"
+ ],
+ "quotaClass": "ai-quotas",
+ "events": [],
+ "implementedBy": [
+ "PUT /api/v1/attribution-quotas/:attribution",
+ "GET /api/v1/attribution-quotas/:attribution",
+ "DELETE /api/v1/attribution-quotas/:attribution"
+ ],
+ "inputSchema": "ai.attribution-quota-put@1",
+ "outputSchema": "ai.attribution-quota@1"
+}
@@ -22,6 +22,7 @@
@@ -22,6 +22,7 @@
"capabilities": [
"capabilities": [
"ai.credential.manage",
"ai.credential.manage",
"ai.provider.manage",
"ai.provider.manage",
+ "ai.quota.attribution.manage",
"ai.run.create",
"ai.run.create",
"ai.run.read",
"ai.run.read",
"ai.usage.read",
"ai.usage.read",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.74.0",
+ "version": "0.75.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",