openvibers/openvibe.contracts Commits
Contracts 0.100.0: usage-sample resource is the rate-card metric, placement-result may select no candidate, chat.ticket.write (planned) (#43)
Changes
@@@ -4,6 +4,26 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) thfrom `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,the notes were in the tag and commit messages (`git tag -n1`).++## 0.100.0 — 2026-10-05++++**Three small contract fixes** (plan follow-ups). Additive and widening, no contract removed.++- `platform.usage-sample@1` now says what `resource` is: the producing service's `platform.rate-card@1` `metric` for++ the reading's `provider` (e.g. `tokens`), never a run, job or object id, with a `unit` that is that metric's unit —++ which is exactly what Billing looks the card up by (`provider` + `resource`, then a unit that fits the metric).++ Without the description AI shipped `resource` as a run id and no card matched. A valid AI reading,++ `fixtures/platform.usage-sample/valid/ai-per-metric.json` (service `ai`, provider `openai`, resource/unit `tokens`),++ and a matching `fixtures/platform.rate-card/valid/ai-tokens.json` ground it.++- `platform.placement-result@1`: `selected` is now `type: [string, null]` and says null means no eligible candidate.++ openvibe-sdk/placement `plan()` already answers `{ selected: null, … }` when nothing qualifies; the string-only++ schema refused the only shape that is sent, so this is recorded in `compatibility/corrections.json` against++ v0.99.0. Valid fixture `fixtures/platform.placement-result/valid/none.json`.++- `chat.ticket-conversation@1` (new, owner `chat`, first-party, **planned**) and the planned `chat.ticket.write`++ capability on Chat's manifest: one conversation per (ticket id, calling service), with a posted message whose++ `author_kind` is `person`, `agent` or `staff`, `author` is the author's subject, `body` the text and `created_at`++ when it was written. It gives Help's service tokens a path into Chat without the person-only `POST /api/chat/send`;++ until Chat implements the route the capability stays out of `generated/openapi/chat.json`. Valid and invalid++ fixtures are in `fixtures/chat.ticket-conversation/`.++## 0.99.0 — 2026-10-04**The estate, generated** (plan T1 step 3). `scripts/estate.js` reads every checkout under the estate root (default@@@ -7,7 +7,7 @@"plan": "OpenVibe Development Roadmap (combined), Wave 1; implementation plan rev 3 section 3.1","deployed": false,"deployment": "none of its own: a library and artifact repository published as release tags; services pin a tag and deploy it with their own releases",-- "contracts": "openvibe-contracts v0.99.0 (this package; the newest tag)",++ "contracts": "openvibe-contracts v0.100.0 (this package; the newest tag)","features": ["589 JSON Schemas with valid and invalid fixtures","31 service manifests with lifecycle declarations",@@@ -18,7 +18,8 @@"generated TypeScript types, JSON Schema bundle and per-service OpenAPI 3.1","compatibility check against the previous tag (scripts/compat.js)","documentation-currency check (scripts/docs-currency.js)",-- "generated estate: docs/ESTATE.md and manifests/repositories/ from the checkouts (scripts/estate.js; --check fails on drift)"++ "generated estate: docs/ESTATE.md and manifests/repositories/ from the checkouts (scripts/estate.js; --check fails on drift)",++ "chat.ticket-conversation@1 and the planned chat.ticket.write capability: a per-ticket conversation keyed by ticket id and calling service, with author_kind person|agent|staff"],-- "updated": "2026-10-04"++ "updated": "2026-10-05"}@@@ -6,6 +6,12 @@"base": "v0.47.0","fixedIn": "0.48.0","reason": "0.47.0 gave network.grant.changed a service-principal payload, but Network's developer relay already sent it for developer-app grants ({ project_id, capability, audience, from, to }) and OpenVibe.Events acts on that shape. Nothing produced or consumed the 0.47.0 shape; it moved to network.principal_grant.changed."++ },++ {++ "id": "platform.placement-result",++ "base": "v0.99.0",++ "fixedIn": "0.100.0",++ "reason": "0.99.0 required `selected` to be a string, but the only producer of this shape, openvibe-sdk/placement plan(), already answers `selected: null` when nothing qualifies (and the POST /api/v1/placement/explain route it describes is roadmap WS-Z9, not built). The schema never matched what is actually sent, so `selected` widens to [string, null]; nothing consumed the string-only shape."}]}@@@ -4701,6 +4701,15 @@"compatibility": "backward","status": "active"},++ {++ "id": "chat.ticket-conversation",++ "version": "1.0.0",++ "owner": "chat",++ "schema": "chat/ticket-conversation.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "planned"++ },{"id": "live.moderation.action","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,78 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/chat/ticket-conversation.v1.json",++ "title": "ChatTicketConversation",++ "description": "chat.ticket-conversation@1: one conversation between an OpenVibe.Help ticket and one calling service, keyed by the ticket id and the service, carrying one posted message. The person side reads and answers it through Chat's person APIs (POST /api/chat/send needs a person's session); a service-side author (Help's agent worker, staff tooling) posts here with a service token, which is why the write needs the chat.ticket.write capability rather than the person send route. author_kind says who wrote the message (`person`, `agent` or `staff`), author is that author's subject, body is the text, and created_at is when the message was written.",++ "$comment": "Additive optional fields may extend this v1 contract.",++ "type": "object",++ "additionalProperties": false,++ "required": [++ "ticket_id",++ "service",++ "message"++ ],++ "properties": {++ "ticket_id": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200,++ "description": "The OpenVibe.Help ticket this conversation belongs to. Together with `service` it keys the conversation: one conversation per (ticket id, calling service)."++ },++ "service": {++ "type": "string",++ "minLength": 1,++ "maxLength": 40,++ "pattern": "^[a-z][a-z0-9-]*$",++ "description": "The Contracts manifest id of the calling service (e.g. `help`, `ai`), the service token's principal. Together with `ticket_id` it keys the conversation, so two services on one ticket get two conversations."++ },++ "message": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "author_kind",++ "author",++ "body",++ "created_at"++ ],++ "properties": {++ "author_kind": {++ "enum": [++ "person",++ "agent",++ "staff"++ ],++ "description": "Who wrote the message: the ticket's `person`, an `agent` (a service acting for one, e.g. Help's AI worker), or `staff` (a human on the service's team)."++ },++ "author": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200,++ "description": "The author's subject: `user:<id>` for a person, or the service/agent subject that posted on its behalf. Never a display name."++ },++ "body": {++ "type": "string",++ "minLength": 1,++ "maxLength": 6000,++ "description": "The message text; not blank."++ },++ "created_at": {++ "type": "string",++ "format": "date-time",++ "description": "When the message was written (the author's clock; Chat keeps its own ordering)."++ }++ }++ }++ },++ "examples": [++ {++ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "help",++ "message": {++ "author_kind": "person",++ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "body": "My export from yesterday is missing the last day of records.",++ "created_at": "2026-10-05T09:00:00Z"++ }++ }++ ]++}@@@ -13,7 +13,11 @@],"properties": {"selected": {-- "type": "string"++ "type": [++ "string",++ "null"++ ],++ "description": "The id of the chosen candidate, or null when none qualified — every candidate was ineligible or none was offered — in which case `reasons` says why. openvibe-sdk/placement plan() returns null on the same condition."},"objective": {"type": "string",@@@ -36,7 +36,8 @@"type": "string"},"resource": {-- "type": "string"++ "type": "string",++ "description": "The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`)."},"provider": {"type": "string"nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "help",++ "message": {++ "author_kind": "bot",++ "author": "agent:agent_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "body": "This author kind is not one of person, agent or staff.",++ "created_at": "2026-10-05T09:02:00Z"++ }++}nnew file mode 100644@@@ -0,0 +1,9 @@++{++ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "help",++ "message": {++ "author_kind": "person",++ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "created_at": "2026-10-05T09:03:00Z"++ }++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "help",++ "message": {++ "author_kind": "agent",++ "author": "agent:agent_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "body": "The export job finished at 23:59 UTC; the last hour is in the next day's file.",++ "created_at": "2026-10-05T09:01:30Z"++ }++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "help",++ "message": {++ "author_kind": "person",++ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "body": "My export from yesterday is missing the last day of records.",++ "created_at": "2026-10-05T09:00:00Z"++ }++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "selected": null,++ "objective": "balanced",++ "candidates": [],++ "decided_at": "2026-10-05T00:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,13 @@++{++ "id": "rc_openai_tokens",++ "provider": "openai",++ "adapter": "openai-v1",++ "metric": "tokens",++ "unit_size": 1000000,++ "unit_price_usd": 0.15,++ "free_allowance": 0,++ "reset_period": "month",++ "effective_from": "2026-09-01",++ "source": "https://openai.com/api/pricing/",++ "verified_at": "2026-09-28"++}nnew file mode 100644@@@ -0,0 +1,15 @@++{++ "id": "use-ai-1",++ "idempotency_key": "ai:run_01JAB2C3D4E5F6G7H8J9K0MNPQ:tokens",++ "service": "ai",++ "subject": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "provider": "openai",++ "resource": "tokens",++ "operation": "chat.completion",++ "quantity": 1500,++ "unit": "tokens",++ "at": "2026-10-02T10:00:00Z",++ "cost_estimate": 0.000225,++ "free_allowance_used": 0,++ "source": "ai.provider-router"++}@@@ -52563,6 +52563,89 @@}}},++ "chat.ticket-conversation": {++ "version": "1.0.0",++ "owner": "chat",++ "status": "planned",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/chat/ticket-conversation.v1.json",++ "title": "ChatTicketConversation",++ "description": "chat.ticket-conversation@1: one conversation between an OpenVibe.Help ticket and one calling service, keyed by the ticket id and the service, carrying one posted message. The person side reads and answers it through Chat's person APIs (POST /api/chat/send needs a person's session); a service-side author (Help's agent worker, staff tooling) posts here with a service token, which is why the write needs the chat.ticket.write capability rather than the person send route. author_kind says who wrote the message (`person`, `agent` or `staff`), author is that author's subject, body is the text, and created_at is when the message was written.",++ "$comment": "Additive optional fields may extend this v1 contract.",++ "type": "object",++ "additionalProperties": false,++ "required": [++ "ticket_id",++ "service",++ "message"++ ],++ "properties": {++ "ticket_id": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200,++ "description": "The OpenVibe.Help ticket this conversation belongs to. Together with `service` it keys the conversation: one conversation per (ticket id, calling service)."++ },++ "service": {++ "type": "string",++ "minLength": 1,++ "maxLength": 40,++ "pattern": "^[a-z][a-z0-9-]*$",++ "description": "The Contracts manifest id of the calling service (e.g. `help`, `ai`), the service token's principal. Together with `ticket_id` it keys the conversation, so two services on one ticket get two conversations."++ },++ "message": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "author_kind",++ "author",++ "body",++ "created_at"++ ],++ "properties": {++ "author_kind": {++ "enum": [++ "person",++ "agent",++ "staff"++ ],++ "description": "Who wrote the message: the ticket's `person`, an `agent` (a service acting for one, e.g. Help's AI worker), or `staff` (a human on the service's team)."++ },++ "author": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200,++ "description": "The author's subject: `user:<id>` for a person, or the service/agent subject that posted on its behalf. Never a display name."++ },++ "body": {++ "type": "string",++ "minLength": 1,++ "maxLength": 6000,++ "description": "The message text; not blank."++ },++ "created_at": {++ "type": "string",++ "format": "date-time",++ "description": "When the message was written (the author's clock; Chat keeps its own ordering)."++ }++ }++ }++ },++ "examples": [++ {++ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "service": "help",++ "message": {++ "author_kind": "person",++ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "body": "My export from yesterday is missing the last day of records.",++ "created_at": "2026-10-05T09:00:00Z"++ }++ }++ ]++ }++ },"live.moderation.action": {"version": "1.0.0","owner": "live",@@@ -61992,7 +62075,11 @@],"properties": {"selected": {-- "type": "string"++ "type": [++ "string",++ "null"++ ],++ "description": "The id of the chosen candidate, or null when none qualified — every candidate was ineligible or none was offered — in which case `reasons` says why. openvibe-sdk/placement plan() returns null on the same condition."},"objective": {"type": "string",@@@ -62619,7 +62706,8 @@"type": "string"},"resource": {-- "type": "string"++ "type": "string",++ "description": "The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`)."},"provider": {"type": "string"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.99.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.99.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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"@@@ -3652,7 +3652,8 @@"type": "string"},"resource": {-- "type": "string"++ "type": "string",++ "description": "The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`)."},"provider": {"type": "string"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.99.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bot API",-- "version": "0.99.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.99.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Space API",-- "version": "0.99.0",-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.100.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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"@@@ -48381,6 +48381,39 @@ export interface ChatSoundAssetRequest {media_asset_id: number;}++/** [email protected] (owner: chat) */++/**++ * chat.ticket-conversation@1: one conversation between an OpenVibe.Help ticket and one calling service, keyed by the ticket id and the service, carrying one posted message. The person side reads and answers it through Chat's person APIs (POST /api/chat/send needs a person's session); a service-side author (Help's agent worker, staff tooling) posts here with a service token, which is why the write needs the chat.ticket.write capability rather than the person send route. author_kind says who wrote the message (`person`, `agent` or `staff`), author is that author's subject, body is the text, and created_at is when the message was written.++ */++export interface ChatTicketConversation {++ /**++ * The OpenVibe.Help ticket this conversation belongs to. Together with `service` it keys the conversation: one conversation per (ticket id, calling service).++ */++ ticket_id: string;++ /**++ * The Contracts manifest id of the calling service (e.g. `help`, `ai`), the service token's principal. Together with `ticket_id` it keys the conversation, so two services on one ticket get two conversations.++ */++ service: string;++ message: {++ /**++ * Who wrote the message: the ticket's `person`, an `agent` (a service acting for one, e.g. Help's AI worker), or `staff` (a human on the service's team).++ */++ author_kind: "person" | "agent" | "staff";++ /**++ * The author's subject: `user:<id>` for a person, or the service/agent subject that posted on its behalf. Never a display name.++ */++ author: string;++ /**++ * The message text; not blank.++ */++ body: string;++ /**++ * When the message was written (the author's clock; Chat keeps its own ordering).++ */++ created_at: string;++ };++}++/** [email protected] (owner: live) *//*** live.moderation.action v1 (OpenVibe.Live server/db/database.js logModerationAction; ADR-022). A staff or channel moderator action taken on OpenVibe.Live outside chat: site and global bans, IP bans, message deletes and purges from Live's admin panel, a stream force-ended, relay users hidden, channel moderators added or removed. Not a person tidying their own messages or configuring their own channel. Written to Live's outbox in the transaction that records the action. OpenVibe.Network keeps it in the moderation audit log. Envelope: subject { type: moderation_action, id: <action_id> }, visibility internal, actor the acting person when known. details is free-form per action (never secrets or message text beyond what moderators saw).@@@ -51781,7 +51814,10 @@ export interface WorkloadRequirements {* Where a workload was (or would be) placed and why: the chosen candidate, the reasons, and every candidate with its eligibility, estimated cost and latency (POST /api/v1/placement/explain; roadmap WS-Z9).*/export interface PlacementResult {-- selected: string;++ /**++ * The id of the chosen candidate, or null when none qualified — every candidate was ineligible or none was offered — in which case `reasons` says why. openvibe-sdk/placement plan() returns null on the same condition.++ */++ selected: string | null;objective:| "cheapest"| "lowest-latency"@@@ -52003,6 +52039,9 @@ export interface UsageSample {service: string;project?: string;subject?: string;++ /**++ * The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`).++ */resource?: string;provider?: string;node?: string;nnew file mode 100644@@@ -0,0 +1,20 @@++{++ "id": "chat.ticket.write",++ "version": "1.0",++ "owner": "chat",++ "status": "planned",++ "visibility": "first-party",++ "sensitive": true,++ "description": "PLANNED (OpenVibe.Help is not built yet; Help's per-ticket conversation has no service-token path into Chat today): create or continue one conversation per (ticket id, calling service) and post a message into it, with author_kind person, agent or staff and the author's subject, so a service (Help's agent worker, staff tooling) can answer a ticket without the person send route POST /api/chat/send, which needs a person's session. Loopback only, first-party service token; never granted to an app or delegated to an agent. It becomes active, and enters generated/openapi/chat.json, when OpenVibe.Chat implements the route.",++ "permissions": [++ "chat:write"++ ],++ "resourceConstraints": [++ "none"++ ],++ "quotaClass": "internal-write",++ "events": [],++ "implementedBy": [],++ "inputSchema": "chat.ticket-conversation@1",++ "outputSchema": "chat.ticket-conversation@1"++}@@@ -24,7 +24,8 @@"chat.presence.read","chat.sounds.read","chat.sounds.write",-- "chat.stats.read"++ "chat.stats.read",++ "chat.ticket.write"],"eventsProduced": ["chat.message.created",@@@ -1,12 +1,12 @@{"name": "openvibe-contracts",-- "version": "0.99.0",++ "version": "0.100.0","lockfileVersion": 3,"requires": true,"packages": {"": {"name": "openvibe-contracts",-- "version": "0.99.0",++ "version": "0.100.0","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.99.0",++ "version": "0.100.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",
@@ -4,6 +4,26 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
@@ -4,6 +4,26 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
the notes were in the tag and commit messages (`git tag -n1`).
+## 0.100.0 — 2026-10-05
+
+**Three small contract fixes** (plan follow-ups). Additive and widening, no contract removed.
+- `platform.usage-sample@1` now says what `resource` is: the producing service's `platform.rate-card@1` `metric` for
+ the reading's `provider` (e.g. `tokens`), never a run, job or object id, with a `unit` that is that metric's unit —
+ which is exactly what Billing looks the card up by (`provider` + `resource`, then a unit that fits the metric).
+ Without the description AI shipped `resource` as a run id and no card matched. A valid AI reading,
+ `fixtures/platform.usage-sample/valid/ai-per-metric.json` (service `ai`, provider `openai`, resource/unit `tokens`),
+ and a matching `fixtures/platform.rate-card/valid/ai-tokens.json` ground it.
+- `platform.placement-result@1`: `selected` is now `type: [string, null]` and says null means no eligible candidate.
+ openvibe-sdk/placement `plan()` already answers `{ selected: null, … }` when nothing qualifies; the string-only
+ schema refused the only shape that is sent, so this is recorded in `compatibility/corrections.json` against
+ v0.99.0. Valid fixture `fixtures/platform.placement-result/valid/none.json`.
+- `chat.ticket-conversation@1` (new, owner `chat`, first-party, **planned**) and the planned `chat.ticket.write`
+ capability on Chat's manifest: one conversation per (ticket id, calling service), with a posted message whose
+ `author_kind` is `person`, `agent` or `staff`, `author` is the author's subject, `body` the text and `created_at`
+ when it was written. It gives Help's service tokens a path into Chat without the person-only `POST /api/chat/send`;
+ until Chat implements the route the capability stays out of `generated/openapi/chat.json`. Valid and invalid
+ fixtures are in `fixtures/chat.ticket-conversation/`.
+
## 0.99.0 — 2026-10-04
## 0.99.0 — 2026-10-04
**The estate, generated** (plan T1 step 3). `scripts/estate.js` reads every checkout under the estate root (default
**The estate, generated** (plan T1 step 3). `scripts/estate.js` reads every checkout under the estate root (default
@@ -7,7 +7,7 @@
@@ -7,7 +7,7 @@
"plan": "OpenVibe Development Roadmap (combined), Wave 1; implementation plan rev 3 section 3.1",
"plan": "OpenVibe Development Roadmap (combined), Wave 1; implementation plan rev 3 section 3.1",
"deployed": false,
"deployed": false,
"deployment": "none of its own: a library and artifact repository published as release tags; services pin a tag and deploy it with their own releases",
"deployment": "none of its own: a library and artifact repository published as release tags; services pin a tag and deploy it with their own releases",
- "contracts": "openvibe-contracts v0.99.0 (this package; the newest tag)",
+ "contracts": "openvibe-contracts v0.100.0 (this package; the newest tag)",
"features": [
"features": [
"589 JSON Schemas with valid and invalid fixtures",
"589 JSON Schemas with valid and invalid fixtures",
"31 service manifests with lifecycle declarations",
"31 service manifests with lifecycle declarations",
@@ -18,7 +18,8 @@
@@ -18,7 +18,8 @@
"generated TypeScript types, JSON Schema bundle and per-service OpenAPI 3.1",
"generated TypeScript types, JSON Schema bundle and per-service OpenAPI 3.1",
"compatibility check against the previous tag (scripts/compat.js)",
"compatibility check against the previous tag (scripts/compat.js)",
"documentation-currency check (scripts/docs-currency.js)",
"documentation-currency check (scripts/docs-currency.js)",
- "generated estate: docs/ESTATE.md and manifests/repositories/ from the checkouts (scripts/estate.js; --check fails on drift)"
+ "generated estate: docs/ESTATE.md and manifests/repositories/ from the checkouts (scripts/estate.js; --check fails on drift)",
+ "chat.ticket-conversation@1 and the planned chat.ticket.write capability: a per-ticket conversation keyed by ticket id and calling service, with author_kind person|agent|staff"
],
],
- "updated": "2026-10-04"
+ "updated": "2026-10-05"
}
}
@@ -6,6 +6,12 @@
@@ -6,6 +6,12 @@
"base": "v0.47.0",
"base": "v0.47.0",
"fixedIn": "0.48.0",
"fixedIn": "0.48.0",
"reason": "0.47.0 gave network.grant.changed a service-principal payload, but Network's developer relay already sent it for developer-app grants ({ project_id, capability, audience, from, to }) and OpenVibe.Events acts on that shape. Nothing produced or consumed the 0.47.0 shape; it moved to network.principal_grant.changed."
"reason": "0.47.0 gave network.grant.changed a service-principal payload, but Network's developer relay already sent it for developer-app grants ({ project_id, capability, audience, from, to }) and OpenVibe.Events acts on that shape. Nothing produced or consumed the 0.47.0 shape; it moved to network.principal_grant.changed."
+ },
+ {
+ "id": "platform.placement-result",
+ "base": "v0.99.0",
+ "fixedIn": "0.100.0",
+ "reason": "0.99.0 required `selected` to be a string, but the only producer of this shape, openvibe-sdk/placement plan(), already answers `selected: null` when nothing qualifies (and the POST /api/v1/placement/explain route it describes is roadmap WS-Z9, not built). The schema never matched what is actually sent, so `selected` widens to [string, null]; nothing consumed the string-only shape."
}
}
]
]
}
}
@@ -4701,6 +4701,15 @@
@@ -4701,6 +4701,15 @@
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
},
},
+ {
+ "id": "chat.ticket-conversation",
+ "version": "1.0.0",
+ "owner": "chat",
+ "schema": "chat/ticket-conversation.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "planned"
+ },
{
{
"id": "live.moderation.action",
"id": "live.moderation.action",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/chat/ticket-conversation.v1.json",
+ "title": "ChatTicketConversation",
+ "description": "chat.ticket-conversation@1: one conversation between an OpenVibe.Help ticket and one calling service, keyed by the ticket id and the service, carrying one posted message. The person side reads and answers it through Chat's person APIs (POST /api/chat/send needs a person's session); a service-side author (Help's agent worker, staff tooling) posts here with a service token, which is why the write needs the chat.ticket.write capability rather than the person send route. author_kind says who wrote the message (`person`, `agent` or `staff`), author is that author's subject, body is the text, and created_at is when the message was written.",
+ "$comment": "Additive optional fields may extend this v1 contract.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "ticket_id",
+ "service",
+ "message"
+ ],
+ "properties": {
+ "ticket_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200,
+ "description": "The OpenVibe.Help ticket this conversation belongs to. Together with `service` it keys the conversation: one conversation per (ticket id, calling service)."
+ },
+ "service": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 40,
+ "pattern": "^[a-z][a-z0-9-]*$",
+ "description": "The Contracts manifest id of the calling service (e.g. `help`, `ai`), the service token's principal. Together with `ticket_id` it keys the conversation, so two services on one ticket get two conversations."
+ },
+ "message": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "author_kind",
+ "author",
+ "body",
+ "created_at"
+ ],
+ "properties": {
+ "author_kind": {
+ "enum": [
+ "person",
+ "agent",
+ "staff"
+ ],
+ "description": "Who wrote the message: the ticket's `person`, an `agent` (a service acting for one, e.g. Help's AI worker), or `staff` (a human on the service's team)."
+ },
+ "author": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200,
+ "description": "The author's subject: `user:<id>` for a person, or the service/agent subject that posted on its behalf. Never a display name."
+ },
+ "body": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 6000,
+ "description": "The message text; not blank."
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the message was written (the author's clock; Chat keeps its own ordering)."
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "help",
+ "message": {
+ "author_kind": "person",
+ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "body": "My export from yesterday is missing the last day of records.",
+ "created_at": "2026-10-05T09:00:00Z"
+ }
+ }
+ ]
+}
@@ -13,7 +13,11 @@
@@ -13,7 +13,11 @@
],
],
"properties": {
"properties": {
"selected": {
"selected": {
- "type": "string"
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The id of the chosen candidate, or null when none qualified — every candidate was ineligible or none was offered — in which case `reasons` says why. openvibe-sdk/placement plan() returns null on the same condition."
},
},
"objective": {
"objective": {
"type": "string",
"type": "string",
@@ -36,7 +36,8 @@
@@ -36,7 +36,8 @@
"type": "string"
"type": "string"
},
},
"resource": {
"resource": {
- "type": "string"
+ "type": "string",
+ "description": "The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`)."
},
},
"provider": {
"provider": {
"type": "string"
"type": "string"
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "help",
+ "message": {
+ "author_kind": "bot",
+ "author": "agent:agent_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "body": "This author kind is not one of person, agent or staff.",
+ "created_at": "2026-10-05T09:02:00Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
+{
+ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "help",
+ "message": {
+ "author_kind": "person",
+ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "created_at": "2026-10-05T09:03:00Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "help",
+ "message": {
+ "author_kind": "agent",
+ "author": "agent:agent_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "body": "The export job finished at 23:59 UTC; the last hour is in the next day's file.",
+ "created_at": "2026-10-05T09:01:30Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "help",
+ "message": {
+ "author_kind": "person",
+ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "body": "My export from yesterday is missing the last day of records.",
+ "created_at": "2026-10-05T09:00:00Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "selected": null,
+ "objective": "balanced",
+ "candidates": [],
+ "decided_at": "2026-10-05T00:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
+{
+ "id": "rc_openai_tokens",
+ "provider": "openai",
+ "adapter": "openai-v1",
+ "metric": "tokens",
+ "unit_size": 1000000,
+ "unit_price_usd": 0.15,
+ "free_allowance": 0,
+ "reset_period": "month",
+ "effective_from": "2026-09-01",
+ "source": "https://openai.com/api/pricing/",
+ "verified_at": "2026-09-28"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
+{
+ "id": "use-ai-1",
+ "idempotency_key": "ai:run_01JAB2C3D4E5F6G7H8J9K0MNPQ:tokens",
+ "service": "ai",
+ "subject": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "provider": "openai",
+ "resource": "tokens",
+ "operation": "chat.completion",
+ "quantity": 1500,
+ "unit": "tokens",
+ "at": "2026-10-02T10:00:00Z",
+ "cost_estimate": 0.000225,
+ "free_allowance_used": 0,
+ "source": "ai.provider-router"
+}
@@ -52563,6 +52563,89 @@
@@ -52563,6 +52563,89 @@
}
}
}
}
},
},
+ "chat.ticket-conversation": {
+ "version": "1.0.0",
+ "owner": "chat",
+ "status": "planned",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/chat/ticket-conversation.v1.json",
+ "title": "ChatTicketConversation",
+ "description": "chat.ticket-conversation@1: one conversation between an OpenVibe.Help ticket and one calling service, keyed by the ticket id and the service, carrying one posted message. The person side reads and answers it through Chat's person APIs (POST /api/chat/send needs a person's session); a service-side author (Help's agent worker, staff tooling) posts here with a service token, which is why the write needs the chat.ticket.write capability rather than the person send route. author_kind says who wrote the message (`person`, `agent` or `staff`), author is that author's subject, body is the text, and created_at is when the message was written.",
+ "$comment": "Additive optional fields may extend this v1 contract.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "ticket_id",
+ "service",
+ "message"
+ ],
+ "properties": {
+ "ticket_id": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200,
+ "description": "The OpenVibe.Help ticket this conversation belongs to. Together with `service` it keys the conversation: one conversation per (ticket id, calling service)."
+ },
+ "service": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 40,
+ "pattern": "^[a-z][a-z0-9-]*$",
+ "description": "The Contracts manifest id of the calling service (e.g. `help`, `ai`), the service token's principal. Together with `ticket_id` it keys the conversation, so two services on one ticket get two conversations."
+ },
+ "message": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "author_kind",
+ "author",
+ "body",
+ "created_at"
+ ],
+ "properties": {
+ "author_kind": {
+ "enum": [
+ "person",
+ "agent",
+ "staff"
+ ],
+ "description": "Who wrote the message: the ticket's `person`, an `agent` (a service acting for one, e.g. Help's AI worker), or `staff` (a human on the service's team)."
+ },
+ "author": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200,
+ "description": "The author's subject: `user:<id>` for a person, or the service/agent subject that posted on its behalf. Never a display name."
+ },
+ "body": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 6000,
+ "description": "The message text; not blank."
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "description": "When the message was written (the author's clock; Chat keeps its own ordering)."
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "ticket_id": "tkt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "service": "help",
+ "message": {
+ "author_kind": "person",
+ "author": "user:usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "body": "My export from yesterday is missing the last day of records.",
+ "created_at": "2026-10-05T09:00:00Z"
+ }
+ }
+ ]
+ }
+ },
"live.moderation.action": {
"live.moderation.action": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "live",
"owner": "live",
@@ -61992,7 +62075,11 @@
@@ -61992,7 +62075,11 @@
],
],
"properties": {
"properties": {
"selected": {
"selected": {
- "type": "string"
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The id of the chosen candidate, or null when none qualified — every candidate was ineligible or none was offered — in which case `reasons` says why. openvibe-sdk/placement plan() returns null on the same condition."
},
},
"objective": {
"objective": {
"type": "string",
"type": "string",
@@ -62619,7 +62706,8 @@
@@ -62619,7 +62706,8 @@
"type": "string"
"type": "string"
},
},
"resource": {
"resource": {
- "type": "string"
+ "type": "string",
+ "description": "The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`)."
},
},
"provider": {
"provider": {
"type": "string"
"type": "string"
@@ -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.99.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"title": "OpenVibe.Billing API",
- "version": "0.99.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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"
@@ -3652,7 +3652,8 @@
@@ -3652,7 +3652,8 @@
"type": "string"
"type": "string"
},
},
"resource": {
"resource": {
- "type": "string"
+ "type": "string",
+ "description": "The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`)."
},
},
"provider": {
"provider": {
"type": "string"
"type": "string"
@@ -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.99.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bot API",
"title": "OpenVibe.Bot API",
- "version": "0.99.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"title": "OpenVibe.Live API",
- "version": "0.99.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Space API",
"title": "OpenVibe.Space API",
- "version": "0.99.0",
- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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.99.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.99.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.100.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.100.0): each operation lists the capabilities it performs; a token for the 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"
@@ -48381,6 +48381,39 @@ export interface ChatSoundAssetRequest {
@@ -48381,6 +48381,39 @@ export interface ChatSoundAssetRequest {
media_asset_id: number;
media_asset_id: number;
}
}
+/** [email protected] (owner: chat) */
+/**
+ * chat.ticket-conversation@1: one conversation between an OpenVibe.Help ticket and one calling service, keyed by the ticket id and the service, carrying one posted message. The person side reads and answers it through Chat's person APIs (POST /api/chat/send needs a person's session); a service-side author (Help's agent worker, staff tooling) posts here with a service token, which is why the write needs the chat.ticket.write capability rather than the person send route. author_kind says who wrote the message (`person`, `agent` or `staff`), author is that author's subject, body is the text, and created_at is when the message was written.
+ */
+export interface ChatTicketConversation {
+ /**
+ * The OpenVibe.Help ticket this conversation belongs to. Together with `service` it keys the conversation: one conversation per (ticket id, calling service).
+ */
+ ticket_id: string;
+ /**
+ * The Contracts manifest id of the calling service (e.g. `help`, `ai`), the service token's principal. Together with `ticket_id` it keys the conversation, so two services on one ticket get two conversations.
+ */
+ service: string;
+ message: {
+ /**
+ * Who wrote the message: the ticket's `person`, an `agent` (a service acting for one, e.g. Help's AI worker), or `staff` (a human on the service's team).
+ */
+ author_kind: "person" | "agent" | "staff";
+ /**
+ * The author's subject: `user:<id>` for a person, or the service/agent subject that posted on its behalf. Never a display name.
+ */
+ author: string;
+ /**
+ * The message text; not blank.
+ */
+ body: string;
+ /**
+ * When the message was written (the author's clock; Chat keeps its own ordering).
+ */
+ created_at: string;
+ };
+}
+
/** [email protected] (owner: live) */
/** [email protected] (owner: live) */
/**
/**
* live.moderation.action v1 (OpenVibe.Live server/db/database.js logModerationAction; ADR-022). A staff or channel moderator action taken on OpenVibe.Live outside chat: site and global bans, IP bans, message deletes and purges from Live's admin panel, a stream force-ended, relay users hidden, channel moderators added or removed. Not a person tidying their own messages or configuring their own channel. Written to Live's outbox in the transaction that records the action. OpenVibe.Network keeps it in the moderation audit log. Envelope: subject { type: moderation_action, id: <action_id> }, visibility internal, actor the acting person when known. details is free-form per action (never secrets or message text beyond what moderators saw).
* live.moderation.action v1 (OpenVibe.Live server/db/database.js logModerationAction; ADR-022). A staff or channel moderator action taken on OpenVibe.Live outside chat: site and global bans, IP bans, message deletes and purges from Live's admin panel, a stream force-ended, relay users hidden, channel moderators added or removed. Not a person tidying their own messages or configuring their own channel. Written to Live's outbox in the transaction that records the action. OpenVibe.Network keeps it in the moderation audit log. Envelope: subject { type: moderation_action, id: <action_id> }, visibility internal, actor the acting person when known. details is free-form per action (never secrets or message text beyond what moderators saw).
@@ -51781,7 +51814,10 @@ export interface WorkloadRequirements {
@@ -51781,7 +51814,10 @@ export interface WorkloadRequirements {
* Where a workload was (or would be) placed and why: the chosen candidate, the reasons, and every candidate with its eligibility, estimated cost and latency (POST /api/v1/placement/explain; roadmap WS-Z9).
* Where a workload was (or would be) placed and why: the chosen candidate, the reasons, and every candidate with its eligibility, estimated cost and latency (POST /api/v1/placement/explain; roadmap WS-Z9).
*/
*/
export interface PlacementResult {
export interface PlacementResult {
- selected: string;
+ /**
+ * The id of the chosen candidate, or null when none qualified — every candidate was ineligible or none was offered — in which case `reasons` says why. openvibe-sdk/placement plan() returns null on the same condition.
+ */
+ selected: string | null;
objective:
objective:
| "cheapest"
| "cheapest"
| "lowest-latency"
| "lowest-latency"
@@ -52003,6 +52039,9 @@ export interface UsageSample {
@@ -52003,6 +52039,9 @@ export interface UsageSample {
service: string;
service: string;
project?: string;
project?: string;
subject?: string;
subject?: string;
+ /**
+ * The producing service's billing resource: the platform.rate-card@1 `metric` for this reading's `provider` (e.g. `tokens`, `queue-operation-64kb`), and never a run, job, object or other work id. The reading's `unit` must be that metric's unit, so Billing rates it against the card found by (provider, resource): a resource that names no card, or a unit the card's metric does not fit, is left unrated (`billing.no_card` / `billing.unit_mismatch`).
+ */
resource?: string;
resource?: string;
provider?: string;
provider?: string;
node?: string;
node?: string;
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+{
+ "id": "chat.ticket.write",
+ "version": "1.0",
+ "owner": "chat",
+ "status": "planned",
+ "visibility": "first-party",
+ "sensitive": true,
+ "description": "PLANNED (OpenVibe.Help is not built yet; Help's per-ticket conversation has no service-token path into Chat today): create or continue one conversation per (ticket id, calling service) and post a message into it, with author_kind person, agent or staff and the author's subject, so a service (Help's agent worker, staff tooling) can answer a ticket without the person send route POST /api/chat/send, which needs a person's session. Loopback only, first-party service token; never granted to an app or delegated to an agent. It becomes active, and enters generated/openapi/chat.json, when OpenVibe.Chat implements the route.",
+ "permissions": [
+ "chat:write"
+ ],
+ "resourceConstraints": [
+ "none"
+ ],
+ "quotaClass": "internal-write",
+ "events": [],
+ "implementedBy": [],
+ "inputSchema": "chat.ticket-conversation@1",
+ "outputSchema": "chat.ticket-conversation@1"
+}
@@ -24,7 +24,8 @@
@@ -24,7 +24,8 @@
"chat.presence.read",
"chat.presence.read",
"chat.sounds.read",
"chat.sounds.read",
"chat.sounds.write",
"chat.sounds.write",
- "chat.stats.read"
+ "chat.stats.read",
+ "chat.ticket.write"
],
],
"eventsProduced": [
"eventsProduced": [
"chat.message.created",
"chat.message.created",
@@ -1,12 +1,12 @@
@@ -1,12 +1,12 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.99.0",
+ "version": "0.100.0",
"lockfileVersion": 3,
"lockfileVersion": 3,
"requires": true,
"requires": true,
"packages": {
"packages": {
"": {
"": {
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.99.0",
+ "version": "0.100.0",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.99.0",
+ "version": "0.100.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",