openvibers/openvibe.contracts Commits
0.340.0: actor.canvas@1, an agent's live panel as data (ADR-059) (#348)
Changes
@@@ -1,4 +1,13 @@# Changelog++++## 0.340.0 — 2026-11-08++++- Add `actor.canvas@1` (ADR-059, plan HO9): an agent's live panel beside the conversation, as data. A canvas is a++ list of blocks (a heading, text, a list, a checklist, a table, a metric, a bar or line chart, a picture from++ openvibe.media, a link, a button) drawn by one renderer (OpenVibe.Shared `ov-canvas.js`) wherever it is shown. There++ is no HTML, style, script or frame; text is plain. A button only sends its label to the agent as the person's own++ message, and ticking a checklist item tells the agent which item changed: a canvas never acts by itself. `version`++ only grows, and the agent replaces the whole document.## 0.339.0 — 2026-11-08- The batches contract says what cancelling does. Only the prompts that never had a run are cancelled, andnnew file mode 100644@@@ -0,0 +1,433 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/actor/canvas.v1.json",++ "title": "ActorCanvas",++ "description": "actor.canvas@1: an agent's live panel beside the conversation (ADR-059) — a board of a trip, a table of prices, a checklist of what is left. It is DATA: a list of blocks drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown (Chat, Surf, the Dock, Actor). There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it; an image is only a picture on openvibe.media; a link opens in a new tab with its host shown. A canvas acts only through the person: a button sends its label to the agent as the person's own message (action ask), and ticking a checklist item tells the agent which item changed; the agent's next steps go through its level and approvals like any other. VERSION only grows: a viewer ignores an older one, and the agent replaces the whole document, never part of it.",++ "type": "object",++ "additionalProperties": false,++ "required": [++ "canvas",++ "id",++ "title",++ "version",++ "blocks",++ "updated_at"++ ],++ "properties": {++ "canvas": {++ "const": "actor.canvas@1"++ },++ "id": {++ "type": "string",++ "pattern": "^cnv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "title": {++ "type": "string",++ "maxLength": 120,++ "minLength": 1++ },++ "version": {++ "type": "integer",++ "minimum": 1,++ "description": "Grows with every update; a viewer ignores an older version."++ },++ "agent_id": {++ "type": "string",++ "pattern": "^agt_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The agent that draws it."++ },++ "thread": {++ "type": "string",++ "maxLength": 64,++ "description": "The conversation it sits beside (Actor's task or chat id)."++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ },++ "blocks": {++ "type": "array",++ "maxItems": 60,++ "items": {++ "oneOf": [++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A heading.",++ "required": [++ "type",++ "text"++ ],++ "properties": {++ "type": {++ "const": "heading"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "text": {++ "type": "string",++ "maxLength": 120,++ "minLength": 1++ },++ "level": {++ "type": "integer",++ "enum": [++ 1,++ 2++ ]++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "Plain text; line breaks are kept, and nothing in it is markup.",++ "required": [++ "type",++ "text"++ ],++ "properties": {++ "type": {++ "const": "text"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "text": {++ "type": "string",++ "maxLength": 4000,++ "minLength": 1++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A list of short lines.",++ "required": [++ "type",++ "items"++ ],++ "properties": {++ "type": {++ "const": "list"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "items": {++ "type": "array",++ "maxItems": 50,++ "items": {++ "type": "string",++ "maxLength": 280,++ "minLength": 1++ }++ },++ "ordered": {++ "type": "boolean"++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "Items the person can tick; a tick tells the agent which item changed.",++ "required": [++ "type",++ "items"++ ],++ "properties": {++ "type": {++ "const": "checklist"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "items": {++ "type": "array",++ "maxItems": 50,++ "items": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "id",++ "text",++ "done"++ ],++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"++ },++ "text": {++ "type": "string",++ "maxLength": 280,++ "minLength": 1++ },++ "done": {++ "type": "boolean"++ }++ }++ }++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A table: up to 8 columns and 100 rows of text or numbers.",++ "required": [++ "type",++ "columns",++ "rows"++ ],++ "properties": {++ "type": {++ "const": "table"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "columns": {++ "type": "array",++ "minItems": 1,++ "maxItems": 8,++ "items": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ }++ },++ "rows": {++ "type": "array",++ "maxItems": 100,++ "items": {++ "type": "array",++ "maxItems": 8,++ "items": {++ "oneOf": [++ {++ "type": "string",++ "maxLength": 200++ },++ {++ "type": "number"++ }++ ]++ }++ }++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "One number that matters, with its label.",++ "required": [++ "type",++ "label",++ "value"++ ],++ "properties": {++ "type": {++ "const": "metric"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "label": {++ "type": "string",++ "maxLength": 60,++ "minLength": 1++ },++ "value": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ },++ "note": {++ "type": "string",++ "maxLength": 120++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A small bar or line chart; the renderer draws it, nothing is fetched.",++ "required": [++ "type",++ "kind",++ "series"++ ],++ "properties": {++ "type": {++ "const": "chart"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "kind": {++ "type": "string",++ "enum": [++ "bar",++ "line"++ ]++ },++ "unit": {++ "type": "string",++ "maxLength": 12++ },++ "series": {++ "type": "array",++ "minItems": 1,++ "maxItems": 4,++ "items": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "name",++ "points"++ ],++ "properties": {++ "name": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ },++ "points": {++ "type": "array",++ "minItems": 1,++ "maxItems": 60,++ "items": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "x",++ "y"++ ],++ "properties": {++ "x": {++ "type": "string",++ "maxLength": 20,++ "minLength": 1++ },++ "y": {++ "type": "number"++ }++ }++ }++ }++ }++ }++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A picture from OpenVibe.Media.",++ "required": [++ "type",++ "src",++ "alt"++ ],++ "properties": {++ "type": {++ "const": "image"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "src": {++ "type": "string",++ "pattern": "^https://openvibe\\.media/[A-Za-z0-9._~/%-]{1,1024}(\\?[A-Za-z0-9._~=&%-]{0,200})?$",++ "description": "A picture on openvibe.media, and nowhere else."++ },++ "alt": {++ "type": "string",++ "maxLength": 200++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A link: it opens in a new tab and shows its host.",++ "required": [++ "type",++ "href",++ "text"++ ],++ "properties": {++ "type": {++ "const": "link"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "href": {++ "type": "string",++ "pattern": "^https://[^\\s\"'<>]{1,2048}$"++ },++ "text": {++ "type": "string",++ "maxLength": 120,++ "minLength": 1++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A reply the person can send with one tap.",++ "required": [++ "type",++ "label",++ "action"++ ],++ "properties": {++ "type": {++ "const": "button"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "label": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ },++ "action": {++ "const": "ask",++ "description": "The label goes to the agent as the person's own message. A button never acts by itself."++ }++ }++ }++ ]++ }++ }++ }++}@@@ -9979,6 +9979,16 @@"status": "active","adr": "ADR-058"},++ {++ "id": "actor.canvas",++ "version": "1.0.0",++ "owner": "actor",++ "schema": "actor/canvas.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-059"++ },{"id": "actor.skill","version": "1.0.0",nnew file mode 100644@@@ -0,0 +1,56 @@++# ADR-059: The canvas — an agent's live panel is data, drawn by one renderer++++- **Status:** Accepted 2026-11-08 (plan track HO, wave 3: HO9).++- **Owner:** OpenVibe.Actor (the canvas belongs to the person's agent and its thread). OpenVibe.Shared draws it, and++ Chat, Surf, the Dock and Actor's own pages show it.++- **Contract:** `actor.canvas@1`.++++## Evidence++++- The study of Hermes and OpenClaw (`plan-state-2026-10-22/hermes-openclaw-2026-11-07.md`, item 13) found that an++ agent which can draw a panel beside the conversation feels like a product rather than a chat: a board of a trip,++ a table of prices, a checklist of what is left.++- OpenClaw's Canvas pushes an HTML document to a panel served by its gateway (`docs/platforms/mac/canvas.md`,++ `src/canvas/`). That works for one person on one machine.++- On OpenVibe a canvas is shown on several sites, to a signed-in person, beside their messages. HTML or script++ written by a model, or by whatever page the model read, would be cross-site scripting by design.++++## Decision++++1. **A canvas is a document of blocks:**++ - heading, text, list, checklist, table, metric, chart (bar or line), image, link and button;++ - `actor.canvas@1` names each block and its limits.++ - There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it.++2. **One renderer** (OpenVibe.Shared `ov-canvas.js`) draws it everywhere, so a canvas looks and behaves the same in++ Chat, Surf, the Dock and Actor.++3. **What leaves the page is bounded:**++ - an image is only a picture on `openvibe.media`;++ - a link opens in a new tab with its host shown;++ - nothing loads from anywhere else.++4. **A canvas acts only through the person:**++ - a button sends its label to the agent as the person's own message (`action: "ask"`), and the agent's next steps++ go through its level and approvals like any other;++ - ticking a checklist item tells the agent which item changed.++ - A canvas never performs an act by itself.++5. **It is live and versioned:** `version` only grows. A viewer ignores an older version, and the agent replaces the++ whole document (at most 60 blocks), never parts of it.++++## Alternatives++++- **HTML widgets (OpenClaw's way).** Rejected: script and style from a model, shown on every OpenVibe site.++- **Markdown only.** Rejected: no tables with numbers, no checklists that answer back, no charts.++- **A canvas per site.** Rejected: one renderer and one contract are what make it the same everywhere.++++## Migration and rollback++++A new contract. Nothing consumes it until Actor stores canvases and Shared draws them. Rollback is retiring the++contract.++++## Tests++++`test/run.js`:++- the fixtures validate, and the invalid ones are refused: an html block, a picture from elsewhere, a button that++ runs something, too many blocks;++- no block type is named html, script, style or iframe;++- a button's only action is `ask`;++- an image's `src` is on `openvibe.media` only.@@@ -52,3 +52,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each| [ADR-056](ADR-056-project-secrets.md) | Project secrets: OpenVibe.Network keeps them per project and environment, write-only (no API returns a value to a person), AES-256-GCM under `NETWORK_SECRETS_KEY`; a service uses one only when the project granted it, to `sign` (HMAC, the value never leaves Network) or to `reveal` it for a listed https origin, through first-party `network.secret.use`; archiving a project shreds its secrets | Accepted 2026-10-15 (plan T13/T17) || [ADR-057](ADR-057-website-connect.md) | Website Connect: a focused Go `quic-go` edge relay for Share, a Node OpenVibe.Connect control API, headscale + embedded `tsnet` for the private mesh with a tenant-isolation proof, and Events-owned durable hook delivery; two-credential node/share tunnel handshake, immediate revocation, edge policy enforcement, no secret or body in audit, a thin MIT SDK boundary, and the single-label `agents-<owner>.openvibe.website` first proof (Universal SSL does not cover `agents.owner.openvibe.website`; deep labels are CON-2); registers 9 v1 contracts and 20 planned capabilities, grants and deploys nothing | Proposed 2026-10-29 (CON-1; plan 2026-10-28 §5.9b), for the owner's review || [ADR-058](ADR-058-skills.md) | Skills: a skill is a document (`actor.skill@1`: a prompt with text resources, an integrity hash that is not a signature, a `requires` that grants nothing and names HO1's approval kinds); the registry's listing (`actor.skill-listing@1`) vouches for the publisher and carries the scan and the curator's state to every site: passed installs in one tap, flagged after the person reads the findings, failed never | Accepted 2026-11-07 (plan HO2, the skeleton) |++| [ADR-059](ADR-059-canvas.md) | The canvas: an agent's live panel is data (`actor.canvas@1`: headings, text, lists, checklists, tables, metrics, bar and line charts, pictures from openvibe.media, links, buttons; no HTML, style, script or frame), drawn by one Shared renderer on every site; a button only sends its label to the agent as the person's message, and a checklist tick tells the agent which item changed | Accepted 2026-11-08 (plan HO9) |nnew file mode 100644@@@ -0,0 +1,16 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Lisbon, 14–17 November",++ "version": 3,++ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "thread": "tsk_42",++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": [++ {++ "type": "button",++ "label": "Delete everything",++ "action": "run"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,16 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Lisbon, 14–17 November",++ "version": 3,++ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "thread": "tsk_42",++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": [++ {++ "type": "image",++ "src": "https://tracker.example/p.png",++ "alt": "x"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,15 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Lisbon, 14–17 November",++ "version": 3,++ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "thread": "tsk_42",++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": [++ {++ "type": "html",++ "html": "<script>alert(1)</script>"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,16 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Lisbon, 14–17 November",++ "version": 3,++ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "thread": "tsk_42",++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": [++ {++ "type": "link",++ "href": "javascript:alert(1)",++ "text": "x"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,255 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Lisbon, 14–17 November",++ "version": 3,++ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "thread": "tsk_42",++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": [++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ },++ {++ "type": "text",++ "text": "x"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Notes",++ "version": 1,++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": []++}nnew file mode 100644@@@ -0,0 +1,103 @@++{++ "canvas": "actor.canvas@1",++ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "title": "Lisbon, 14–17 November",++ "version": 3,++ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",++ "thread": "tsk_42",++ "updated_at": "2026-11-08T01:00:00.000Z",++ "blocks": [++ {++ "type": "heading",++ "text": "Lisbon, 14–17 November",++ "level": 1++ },++ {++ "type": "metric",++ "label": "Flights and hotel",++ "value": "€612",++ "note": "two people, booked nothing yet"++ },++ {++ "type": "checklist",++ "id": "todo",++ "items": [++ {++ "id": "flights",++ "text": "Pick the flights",++ "done": true++ },++ {++ "id": "hotel",++ "text": "Choose a hotel near Alfama",++ "done": false++ }++ ]++ },++ {++ "type": "table",++ "id": "hotels",++ "columns": [++ "Hotel",++ "Night",++ "Walk to the river"++ ],++ "rows": [++ [++ "Casa A",++ 118,++ "6 min"++ ],++ [++ "Hotel B",++ 96,++ "14 min"++ ]++ ]++ },++ {++ "type": "chart",++ "id": "prices",++ "kind": "line",++ "unit": "€",++ "series": [++ {++ "name": "Flights",++ "points": [++ {++ "x": "Mon",++ "y": 240++ },++ {++ "x": "Tue",++ "y": 212++ },++ {++ "x": "Wed",++ "y": 199++ }++ ]++ }++ ]++ },++ {++ "type": "image",++ "src": "https://openvibe.media/t/lisbon.jpg",++ "alt": "The river at dusk"++ },++ {++ "type": "link",++ "href": "https://openvibe.video/watch?v=AbCdEfGhIjK",++ "text": "The walking tour video"++ },++ {++ "type": "text",++ "text": "Casa A is closer to the river; Hotel B is cheaper.\nBoth have free cancellation until Friday."++ },++ {++ "type": "button",++ "label": "Book Casa A",++ "action": "ask"++ }++ ]++}@@@ -110142,6 +110142,444 @@}}},++ "actor.canvas": {++ "version": "1.0.0",++ "owner": "actor",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/actor/canvas.v1.json",++ "title": "ActorCanvas",++ "description": "actor.canvas@1: an agent's live panel beside the conversation (ADR-059) — a board of a trip, a table of prices, a checklist of what is left. It is DATA: a list of blocks drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown (Chat, Surf, the Dock, Actor). There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it; an image is only a picture on openvibe.media; a link opens in a new tab with its host shown. A canvas acts only through the person: a button sends its label to the agent as the person's own message (action ask), and ticking a checklist item tells the agent which item changed; the agent's next steps go through its level and approvals like any other. VERSION only grows: a viewer ignores an older one, and the agent replaces the whole document, never part of it.",++ "type": "object",++ "additionalProperties": false,++ "required": [++ "canvas",++ "id",++ "title",++ "version",++ "blocks",++ "updated_at"++ ],++ "properties": {++ "canvas": {++ "const": "actor.canvas@1"++ },++ "id": {++ "type": "string",++ "pattern": "^cnv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "title": {++ "type": "string",++ "maxLength": 120,++ "minLength": 1++ },++ "version": {++ "type": "integer",++ "minimum": 1,++ "description": "Grows with every update; a viewer ignores an older version."++ },++ "agent_id": {++ "type": "string",++ "pattern": "^agt_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "The agent that draws it."++ },++ "thread": {++ "type": "string",++ "maxLength": 64,++ "description": "The conversation it sits beside (Actor's task or chat id)."++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ },++ "blocks": {++ "type": "array",++ "maxItems": 60,++ "items": {++ "oneOf": [++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A heading.",++ "required": [++ "type",++ "text"++ ],++ "properties": {++ "type": {++ "const": "heading"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "text": {++ "type": "string",++ "maxLength": 120,++ "minLength": 1++ },++ "level": {++ "type": "integer",++ "enum": [++ 1,++ 2++ ]++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "Plain text; line breaks are kept, and nothing in it is markup.",++ "required": [++ "type",++ "text"++ ],++ "properties": {++ "type": {++ "const": "text"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "text": {++ "type": "string",++ "maxLength": 4000,++ "minLength": 1++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A list of short lines.",++ "required": [++ "type",++ "items"++ ],++ "properties": {++ "type": {++ "const": "list"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "items": {++ "type": "array",++ "maxItems": 50,++ "items": {++ "type": "string",++ "maxLength": 280,++ "minLength": 1++ }++ },++ "ordered": {++ "type": "boolean"++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "Items the person can tick; a tick tells the agent which item changed.",++ "required": [++ "type",++ "items"++ ],++ "properties": {++ "type": {++ "const": "checklist"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "items": {++ "type": "array",++ "maxItems": 50,++ "items": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "id",++ "text",++ "done"++ ],++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"++ },++ "text": {++ "type": "string",++ "maxLength": 280,++ "minLength": 1++ },++ "done": {++ "type": "boolean"++ }++ }++ }++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A table: up to 8 columns and 100 rows of text or numbers.",++ "required": [++ "type",++ "columns",++ "rows"++ ],++ "properties": {++ "type": {++ "const": "table"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "columns": {++ "type": "array",++ "minItems": 1,++ "maxItems": 8,++ "items": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ }++ },++ "rows": {++ "type": "array",++ "maxItems": 100,++ "items": {++ "type": "array",++ "maxItems": 8,++ "items": {++ "oneOf": [++ {++ "type": "string",++ "maxLength": 200++ },++ {++ "type": "number"++ }++ ]++ }++ }++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "One number that matters, with its label.",++ "required": [++ "type",++ "label",++ "value"++ ],++ "properties": {++ "type": {++ "const": "metric"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "label": {++ "type": "string",++ "maxLength": 60,++ "minLength": 1++ },++ "value": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ },++ "note": {++ "type": "string",++ "maxLength": 120++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A small bar or line chart; the renderer draws it, nothing is fetched.",++ "required": [++ "type",++ "kind",++ "series"++ ],++ "properties": {++ "type": {++ "const": "chart"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "kind": {++ "type": "string",++ "enum": [++ "bar",++ "line"++ ]++ },++ "unit": {++ "type": "string",++ "maxLength": 12++ },++ "series": {++ "type": "array",++ "minItems": 1,++ "maxItems": 4,++ "items": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "name",++ "points"++ ],++ "properties": {++ "name": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ },++ "points": {++ "type": "array",++ "minItems": 1,++ "maxItems": 60,++ "items": {++ "type": "object",++ "additionalProperties": false,++ "required": [++ "x",++ "y"++ ],++ "properties": {++ "x": {++ "type": "string",++ "maxLength": 20,++ "minLength": 1++ },++ "y": {++ "type": "number"++ }++ }++ }++ }++ }++ }++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A picture from OpenVibe.Media.",++ "required": [++ "type",++ "src",++ "alt"++ ],++ "properties": {++ "type": {++ "const": "image"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "src": {++ "type": "string",++ "pattern": "^https://openvibe\\.media/[A-Za-z0-9._~/%-]{1,1024}(\\?[A-Za-z0-9._~=&%-]{0,200})?$",++ "description": "A picture on openvibe.media, and nowhere else."++ },++ "alt": {++ "type": "string",++ "maxLength": 200++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A link: it opens in a new tab and shows its host.",++ "required": [++ "type",++ "href",++ "text"++ ],++ "properties": {++ "type": {++ "const": "link"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "href": {++ "type": "string",++ "pattern": "^https://[^\\s\"'<>]{1,2048}$"++ },++ "text": {++ "type": "string",++ "maxLength": 120,++ "minLength": 1++ }++ }++ },++ {++ "type": "object",++ "additionalProperties": false,++ "description": "A reply the person can send with one tap.",++ "required": [++ "type",++ "label",++ "action"++ ],++ "properties": {++ "type": {++ "const": "button"++ },++ "id": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",++ "description": "A stable id, so a viewer keeps its place when the canvas updates."++ },++ "label": {++ "type": "string",++ "maxLength": 40,++ "minLength": 1++ },++ "action": {++ "const": "ask",++ "description": "The label goes to the agent as the person's own message. A button never acts by itself."++ }++ }++ }++ ]++ }++ }++ }++ }++ },"actor.skill": {"version": "1.0.0","owner": "actor",@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Actor API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bench API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe Connect API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Design API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Domains API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Food API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Inventory API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Mail API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.MediaHub API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenRestream API",-- "version": "0.339.0",-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Play API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Quest API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Report API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Run API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Services API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Today API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Vision API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Watch API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Work API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Zone API",-- "version": "0.339.0",-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",++ "version": "0.340.0",++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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"@@@ -301554,6 +301554,363 @@ export interface ActorSkillListing {retired_at?: string;}++/** [email protected] (owner: actor) */++/**++ * actor.canvas@1: an agent's live panel beside the conversation (ADR-059) — a board of a trip, a table of prices, a checklist of what is left. It is DATA: a list of blocks drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown (Chat, Surf, the Dock, Actor). There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it; an image is only a picture on openvibe.media; a link opens in a new tab with its host shown. A canvas acts only through the person: a button sends its label to the agent as the person's own message (action ask), and ticking a checklist item tells the agent which item changed; the agent's next steps go through its level and approvals like any other. VERSION only grows: a viewer ignores an older one, and the agent replaces the whole document, never part of it.++ */++export interface ActorCanvas {++ canvas: "actor.canvas@1";++ id: string;++ title: string;++ /**++ * Grows with every update; a viewer ignores an older version.++ */++ version: number;++ /**++ * The agent that draws it.++ */++ agent_id?: string;++ /**++ * The conversation it sits beside (Actor's task or chat id).++ */++ thread?: string;++ updated_at: string;++ /**++ * @maxItems 60++ */++ blocks: (++ | {++ type: "heading";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ text: string;++ level?: 1 | 2;++ }++ | {++ type: "text";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ text: string;++ }++ | {++ type: "list";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ /**++ * @maxItems 50++ */++ items: string[];++ ordered?: boolean;++ }++ | {++ type: "checklist";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ /**++ * @maxItems 50++ */++ items: {++ id: string;++ text: string;++ done: boolean;++ }[];++ }++ | {++ type: "table";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ /**++ * @minItems 1++ * @maxItems 8++ */++ columns:++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string];++ /**++ * @maxItems 100++ */++ rows:++ | []++ | [string | number]++ | [string | number, string | number]++ | [string | number, string | number, string | number]++ | [string | number, string | number, string | number, string | number]++ | [string | number, string | number, string | number, string | number, string | number]++ | [string | number, string | number, string | number, string | number, string | number, string | number]++ | [++ string | number,++ string | number,++ string | number,++ string | number,++ string | number,++ string | number,++ string | number++ ]++ | [++ string | number,++ string | number,++ string | number,++ string | number,++ string | number,++ string | number,++ string | number,++ string | number++ ][];++ }++ | {++ type: "metric";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ label: string;++ value: string;++ note?: string;++ }++ | {++ type: "chart";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ kind: "bar" | "line";++ unit?: string;++ /**++ * @minItems 1++ * @maxItems 4++ */++ series:++ | [++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ }++ ]++ | [++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ },++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ }++ ]++ | [++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ },++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ },++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ }++ ]++ | [++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ },++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ },++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ },++ {++ name: string;++ /**++ * @minItems 1++ * @maxItems 60++ */++ points: [++ {++ x: string;++ y: number;++ },++ ...{++ x: string;++ y: number;++ }[]++ ];++ }++ ];++ }++ | {++ type: "image";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ /**++ * A picture on openvibe.media, and nowhere else.++ */++ src: string;++ alt: string;++ }++ | {++ type: "link";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ href: string;++ text: string;++ }++ | {++ type: "button";++ /**++ * A stable id, so a viewer keeps its place when the canvas updates.++ */++ id?: string;++ label: string;++ /**++ * The label goes to the agent as the person's own message. A button never acts by itself.++ */++ action: "ask";++ }++ )[];++}++/** [email protected] (owner: actor) *//*** actor.skill@1: a skill, the document an agent loads to do one kind of job well (ADR-058). It follows the open Markdown-skill shape (a name, a one-line description, Markdown instructions) with what OpenVibe adds: a slug, a version, up to ten TEXT resources, and REQUIRES, what the skill may ask an agent to do. A skill GRANTS NOTHING: requires only declares; the agent's level and approvals decide every step (actor approvals, HO1), and a step of a kind the skill did not declare is a scan finding (actor.skill-listing@1). A v1 skill RUNS AS A PROMPT and nothing else: no code, no binary, no install recipe (a skill that runs code waits for a sandbox and a new major). DESCRIPTION is the only part an agent reads before it loads the skill (progressive disclosure), so it says when to use it. The INTEGRITY block is a sha256 over the canonical JSON of the document: it shows the file was not edited after it was written and says nothing about who wrote it, so the AUTHOR is a claim; the registry's listing is the only place a publisher is vouched for. The canonical JSON is the document's own fields, in this order: skill, slug, name, description, version, instructions, resources, requires, runs, license, author; an optional field that is absent or empty is left out; resources are [{ path, media_type, text }] in the document's order; requires is { kinds, apps, hosts } with empty lists left out; author is { subject } or { subject, name }; the value is the compact JSON of that object (no spaces). CREATED_AT is not hashed.@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.339.0",++ "version": "0.340.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",@@@ -1022,6 +1022,20 @@ sub(path.join(__dirname, 'changelog-history.test.js'));ok(dangling.length === 0, `generated types reference undeclared names: ${dangling.join(', ')}`);}++// ── actor.canvas@1 (ADR-059): data, never markup; a button only asks ─────────++{++ const c = contracts.schema('actor.canvas@1');++ const types = c.properties.blocks.items.oneOf.map((b) => b.properties.type.const);++ ok(!types.some((t) => /^(html|script|style|iframe|frame|embed|markup)$/i.test(t)), 'no canvas block is markup, a script, a style or a frame');++ const button = c.properties.blocks.items.oneOf.find((b) => b.properties.type.const === 'button');++ ok(button.properties.action.const === 'ask', 'a button only sends its label to the agent as the person\'s message');++ const image = c.properties.blocks.items.oneOf.find((b) => b.properties.type.const === 'image');++ ok(new RegExp(image.properties.src.pattern).test('https://openvibe.media/t/x.jpg') && !new RegExp(image.properties.src.pattern).test('https://tracker.example/p.png'), 'a picture comes from openvibe.media only');++ const link = c.properties.blocks.items.oneOf.find((b) => b.properties.type.const === 'link');++ ok(!new RegExp(link.properties.href.pattern).test('javascript:alert(1)') && !new RegExp(link.properties.href.pattern).test('http://x.y'), 'a link is https only');++ ok(c.properties.blocks.maxItems === 60, 'at most 60 blocks');++}++// ── actor.skill@1 and actor.skill-listing@1 (ADR-058) ───────────────────────// A skill is a document: its integrity hash covers its canonical content (not a signature); it runs as a prompt// only; it grants nothing, and what it may ask for is HO1's kinds; the listing's scan and curator travel with it.
@@ -1,4 +1,13 @@
@@ -1,4 +1,13 @@
# Changelog
# Changelog
+
+## 0.340.0 — 2026-11-08
+
+- Add `actor.canvas@1` (ADR-059, plan HO9): an agent's live panel beside the conversation, as data. A canvas is a
+ list of blocks (a heading, text, a list, a checklist, a table, a metric, a bar or line chart, a picture from
+ openvibe.media, a link, a button) drawn by one renderer (OpenVibe.Shared `ov-canvas.js`) wherever it is shown. There
+ is no HTML, style, script or frame; text is plain. A button only sends its label to the agent as the person's own
+ message, and ticking a checklist item tells the agent which item changed: a canvas never acts by itself. `version`
+ only grows, and the agent replaces the whole document.
## 0.339.0 — 2026-11-08
## 0.339.0 — 2026-11-08
- The batches contract says what cancelling does. Only the prompts that never had a run are cancelled, and
- The batches contract says what cancelling does. Only the prompts that never had a run are cancelled, and
new file mode 100644
new file mode 100644
@@ -0,0 +1,433 @@
@@ -0,0 +1,433 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/actor/canvas.v1.json",
+ "title": "ActorCanvas",
+ "description": "actor.canvas@1: an agent's live panel beside the conversation (ADR-059) — a board of a trip, a table of prices, a checklist of what is left. It is DATA: a list of blocks drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown (Chat, Surf, the Dock, Actor). There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it; an image is only a picture on openvibe.media; a link opens in a new tab with its host shown. A canvas acts only through the person: a button sends its label to the agent as the person's own message (action ask), and ticking a checklist item tells the agent which item changed; the agent's next steps go through its level and approvals like any other. VERSION only grows: a viewer ignores an older one, and the agent replaces the whole document, never part of it.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "canvas",
+ "id",
+ "title",
+ "version",
+ "blocks",
+ "updated_at"
+ ],
+ "properties": {
+ "canvas": {
+ "const": "actor.canvas@1"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^cnv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "title": {
+ "type": "string",
+ "maxLength": 120,
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Grows with every update; a viewer ignores an older version."
+ },
+ "agent_id": {
+ "type": "string",
+ "pattern": "^agt_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The agent that draws it."
+ },
+ "thread": {
+ "type": "string",
+ "maxLength": 64,
+ "description": "The conversation it sits beside (Actor's task or chat id)."
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "blocks": {
+ "type": "array",
+ "maxItems": 60,
+ "items": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A heading.",
+ "required": [
+ "type",
+ "text"
+ ],
+ "properties": {
+ "type": {
+ "const": "heading"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 120,
+ "minLength": 1
+ },
+ "level": {
+ "type": "integer",
+ "enum": [
+ 1,
+ 2
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Plain text; line breaks are kept, and nothing in it is markup.",
+ "required": [
+ "type",
+ "text"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 4000,
+ "minLength": 1
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A list of short lines.",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "items": {
+ "type": "array",
+ "maxItems": 50,
+ "items": {
+ "type": "string",
+ "maxLength": 280,
+ "minLength": 1
+ }
+ },
+ "ordered": {
+ "type": "boolean"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Items the person can tick; a tick tells the agent which item changed.",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "checklist"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "items": {
+ "type": "array",
+ "maxItems": 50,
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "id",
+ "text",
+ "done"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 280,
+ "minLength": 1
+ },
+ "done": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A table: up to 8 columns and 100 rows of text or numbers.",
+ "required": [
+ "type",
+ "columns",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "columns": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 8,
+ "items": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ }
+ },
+ "rows": {
+ "type": "array",
+ "maxItems": 100,
+ "items": {
+ "type": "array",
+ "maxItems": 8,
+ "items": {
+ "oneOf": [
+ {
+ "type": "string",
+ "maxLength": 200
+ },
+ {
+ "type": "number"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "One number that matters, with its label.",
+ "required": [
+ "type",
+ "label",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "metric"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "label": {
+ "type": "string",
+ "maxLength": 60,
+ "minLength": 1
+ },
+ "value": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ },
+ "note": {
+ "type": "string",
+ "maxLength": 120
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A small bar or line chart; the renderer draws it, nothing is fetched.",
+ "required": [
+ "type",
+ "kind",
+ "series"
+ ],
+ "properties": {
+ "type": {
+ "const": "chart"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "kind": {
+ "type": "string",
+ "enum": [
+ "bar",
+ "line"
+ ]
+ },
+ "unit": {
+ "type": "string",
+ "maxLength": 12
+ },
+ "series": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 4,
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "name",
+ "points"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ },
+ "points": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 60,
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "x",
+ "y"
+ ],
+ "properties": {
+ "x": {
+ "type": "string",
+ "maxLength": 20,
+ "minLength": 1
+ },
+ "y": {
+ "type": "number"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A picture from OpenVibe.Media.",
+ "required": [
+ "type",
+ "src",
+ "alt"
+ ],
+ "properties": {
+ "type": {
+ "const": "image"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "src": {
+ "type": "string",
+ "pattern": "^https://openvibe\\.media/[A-Za-z0-9._~/%-]{1,1024}(\\?[A-Za-z0-9._~=&%-]{0,200})?$",
+ "description": "A picture on openvibe.media, and nowhere else."
+ },
+ "alt": {
+ "type": "string",
+ "maxLength": 200
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A link: it opens in a new tab and shows its host.",
+ "required": [
+ "type",
+ "href",
+ "text"
+ ],
+ "properties": {
+ "type": {
+ "const": "link"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "href": {
+ "type": "string",
+ "pattern": "^https://[^\\s\"'<>]{1,2048}$"
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 120,
+ "minLength": 1
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A reply the person can send with one tap.",
+ "required": [
+ "type",
+ "label",
+ "action"
+ ],
+ "properties": {
+ "type": {
+ "const": "button"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "label": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ },
+ "action": {
+ "const": "ask",
+ "description": "The label goes to the agent as the person's own message. A button never acts by itself."
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+}
@@ -9979,6 +9979,16 @@
@@ -9979,6 +9979,16 @@
"status": "active",
"status": "active",
"adr": "ADR-058"
"adr": "ADR-058"
},
},
+ {
+ "id": "actor.canvas",
+ "version": "1.0.0",
+ "owner": "actor",
+ "schema": "actor/canvas.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-059"
+ },
{
{
"id": "actor.skill",
"id": "actor.skill",
"version": "1.0.0",
"version": "1.0.0",
new file mode 100644
new file mode 100644
@@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
+# ADR-059: The canvas — an agent's live panel is data, drawn by one renderer
+
+- **Status:** Accepted 2026-11-08 (plan track HO, wave 3: HO9).
+- **Owner:** OpenVibe.Actor (the canvas belongs to the person's agent and its thread). OpenVibe.Shared draws it, and
+ Chat, Surf, the Dock and Actor's own pages show it.
+- **Contract:** `actor.canvas@1`.
+
+## Evidence
+
+- The study of Hermes and OpenClaw (`plan-state-2026-10-22/hermes-openclaw-2026-11-07.md`, item 13) found that an
+ agent which can draw a panel beside the conversation feels like a product rather than a chat: a board of a trip,
+ a table of prices, a checklist of what is left.
+- OpenClaw's Canvas pushes an HTML document to a panel served by its gateway (`docs/platforms/mac/canvas.md`,
+ `src/canvas/`). That works for one person on one machine.
+- On OpenVibe a canvas is shown on several sites, to a signed-in person, beside their messages. HTML or script
+ written by a model, or by whatever page the model read, would be cross-site scripting by design.
+
+## Decision
+
+1. **A canvas is a document of blocks:**
+ - heading, text, list, checklist, table, metric, chart (bar or line), image, link and button;
+ - `actor.canvas@1` names each block and its limits.
+ - There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it.
+2. **One renderer** (OpenVibe.Shared `ov-canvas.js`) draws it everywhere, so a canvas looks and behaves the same in
+ Chat, Surf, the Dock and Actor.
+3. **What leaves the page is bounded:**
+ - an image is only a picture on `openvibe.media`;
+ - a link opens in a new tab with its host shown;
+ - nothing loads from anywhere else.
+4. **A canvas acts only through the person:**
+ - a button sends its label to the agent as the person's own message (`action: "ask"`), and the agent's next steps
+ go through its level and approvals like any other;
+ - ticking a checklist item tells the agent which item changed.
+ - A canvas never performs an act by itself.
+5. **It is live and versioned:** `version` only grows. A viewer ignores an older version, and the agent replaces the
+ whole document (at most 60 blocks), never parts of it.
+
+## Alternatives
+
+- **HTML widgets (OpenClaw's way).** Rejected: script and style from a model, shown on every OpenVibe site.
+- **Markdown only.** Rejected: no tables with numbers, no checklists that answer back, no charts.
+- **A canvas per site.** Rejected: one renderer and one contract are what make it the same everywhere.
+
+## Migration and rollback
+
+A new contract. Nothing consumes it until Actor stores canvases and Shared draws them. Rollback is retiring the
+contract.
+
+## Tests
+
+`test/run.js`:
+- the fixtures validate, and the invalid ones are refused: an html block, a picture from elsewhere, a button that
+ runs something, too many blocks;
+- no block type is named html, script, style or iframe;
+- a button's only action is `ask`;
+- an image's `src` is on `openvibe.media` only.
@@ -52,3 +52,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each
@@ -52,3 +52,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each
| [ADR-056](ADR-056-project-secrets.md) | Project secrets: OpenVibe.Network keeps them per project and environment, write-only (no API returns a value to a person), AES-256-GCM under `NETWORK_SECRETS_KEY`; a service uses one only when the project granted it, to `sign` (HMAC, the value never leaves Network) or to `reveal` it for a listed https origin, through first-party `network.secret.use`; archiving a project shreds its secrets | Accepted 2026-10-15 (plan T13/T17) |
| [ADR-056](ADR-056-project-secrets.md) | Project secrets: OpenVibe.Network keeps them per project and environment, write-only (no API returns a value to a person), AES-256-GCM under `NETWORK_SECRETS_KEY`; a service uses one only when the project granted it, to `sign` (HMAC, the value never leaves Network) or to `reveal` it for a listed https origin, through first-party `network.secret.use`; archiving a project shreds its secrets | Accepted 2026-10-15 (plan T13/T17) |
| [ADR-057](ADR-057-website-connect.md) | Website Connect: a focused Go `quic-go` edge relay for Share, a Node OpenVibe.Connect control API, headscale + embedded `tsnet` for the private mesh with a tenant-isolation proof, and Events-owned durable hook delivery; two-credential node/share tunnel handshake, immediate revocation, edge policy enforcement, no secret or body in audit, a thin MIT SDK boundary, and the single-label `agents-<owner>.openvibe.website` first proof (Universal SSL does not cover `agents.owner.openvibe.website`; deep labels are CON-2); registers 9 v1 contracts and 20 planned capabilities, grants and deploys nothing | Proposed 2026-10-29 (CON-1; plan 2026-10-28 §5.9b), for the owner's review |
| [ADR-057](ADR-057-website-connect.md) | Website Connect: a focused Go `quic-go` edge relay for Share, a Node OpenVibe.Connect control API, headscale + embedded `tsnet` for the private mesh with a tenant-isolation proof, and Events-owned durable hook delivery; two-credential node/share tunnel handshake, immediate revocation, edge policy enforcement, no secret or body in audit, a thin MIT SDK boundary, and the single-label `agents-<owner>.openvibe.website` first proof (Universal SSL does not cover `agents.owner.openvibe.website`; deep labels are CON-2); registers 9 v1 contracts and 20 planned capabilities, grants and deploys nothing | Proposed 2026-10-29 (CON-1; plan 2026-10-28 §5.9b), for the owner's review |
| [ADR-058](ADR-058-skills.md) | Skills: a skill is a document (`actor.skill@1`: a prompt with text resources, an integrity hash that is not a signature, a `requires` that grants nothing and names HO1's approval kinds); the registry's listing (`actor.skill-listing@1`) vouches for the publisher and carries the scan and the curator's state to every site: passed installs in one tap, flagged after the person reads the findings, failed never | Accepted 2026-11-07 (plan HO2, the skeleton) |
| [ADR-058](ADR-058-skills.md) | Skills: a skill is a document (`actor.skill@1`: a prompt with text resources, an integrity hash that is not a signature, a `requires` that grants nothing and names HO1's approval kinds); the registry's listing (`actor.skill-listing@1`) vouches for the publisher and carries the scan and the curator's state to every site: passed installs in one tap, flagged after the person reads the findings, failed never | Accepted 2026-11-07 (plan HO2, the skeleton) |
+| [ADR-059](ADR-059-canvas.md) | The canvas: an agent's live panel is data (`actor.canvas@1`: headings, text, lists, checklists, tables, metrics, bar and line charts, pictures from openvibe.media, links, buttons; no HTML, style, script or frame), drawn by one Shared renderer on every site; a button only sends its label to the agent as the person's message, and a checklist tick tells the agent which item changed | Accepted 2026-11-08 (plan HO9) |
new file mode 100644
new file mode 100644
@@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Lisbon, 14–17 November",
+ "version": 3,
+ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "thread": "tsk_42",
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": [
+ {
+ "type": "button",
+ "label": "Delete everything",
+ "action": "run"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Lisbon, 14–17 November",
+ "version": 3,
+ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "thread": "tsk_42",
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": [
+ {
+ "type": "image",
+ "src": "https://tracker.example/p.png",
+ "alt": "x"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Lisbon, 14–17 November",
+ "version": 3,
+ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "thread": "tsk_42",
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": [
+ {
+ "type": "html",
+ "html": "<script>alert(1)</script>"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Lisbon, 14–17 November",
+ "version": 3,
+ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "thread": "tsk_42",
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": [
+ {
+ "type": "link",
+ "href": "javascript:alert(1)",
+ "text": "x"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,255 @@
@@ -0,0 +1,255 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Lisbon, 14–17 November",
+ "version": 3,
+ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "thread": "tsk_42",
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": [
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ },
+ {
+ "type": "text",
+ "text": "x"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Notes",
+ "version": 1,
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
+{
+ "canvas": "actor.canvas@1",
+ "id": "cnv_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "title": "Lisbon, 14–17 November",
+ "version": 3,
+ "agent_id": "agt_01JAB2C3D4E5F6G7H8J9K0MNPQ",
+ "thread": "tsk_42",
+ "updated_at": "2026-11-08T01:00:00.000Z",
+ "blocks": [
+ {
+ "type": "heading",
+ "text": "Lisbon, 14–17 November",
+ "level": 1
+ },
+ {
+ "type": "metric",
+ "label": "Flights and hotel",
+ "value": "€612",
+ "note": "two people, booked nothing yet"
+ },
+ {
+ "type": "checklist",
+ "id": "todo",
+ "items": [
+ {
+ "id": "flights",
+ "text": "Pick the flights",
+ "done": true
+ },
+ {
+ "id": "hotel",
+ "text": "Choose a hotel near Alfama",
+ "done": false
+ }
+ ]
+ },
+ {
+ "type": "table",
+ "id": "hotels",
+ "columns": [
+ "Hotel",
+ "Night",
+ "Walk to the river"
+ ],
+ "rows": [
+ [
+ "Casa A",
+ 118,
+ "6 min"
+ ],
+ [
+ "Hotel B",
+ 96,
+ "14 min"
+ ]
+ ]
+ },
+ {
+ "type": "chart",
+ "id": "prices",
+ "kind": "line",
+ "unit": "€",
+ "series": [
+ {
+ "name": "Flights",
+ "points": [
+ {
+ "x": "Mon",
+ "y": 240
+ },
+ {
+ "x": "Tue",
+ "y": 212
+ },
+ {
+ "x": "Wed",
+ "y": 199
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "image",
+ "src": "https://openvibe.media/t/lisbon.jpg",
+ "alt": "The river at dusk"
+ },
+ {
+ "type": "link",
+ "href": "https://openvibe.video/watch?v=AbCdEfGhIjK",
+ "text": "The walking tour video"
+ },
+ {
+ "type": "text",
+ "text": "Casa A is closer to the river; Hotel B is cheaper.\nBoth have free cancellation until Friday."
+ },
+ {
+ "type": "button",
+ "label": "Book Casa A",
+ "action": "ask"
+ }
+ ]
+}
@@ -110142,6 +110142,444 @@
@@ -110142,6 +110142,444 @@
}
}
}
}
},
},
+ "actor.canvas": {
+ "version": "1.0.0",
+ "owner": "actor",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/actor/canvas.v1.json",
+ "title": "ActorCanvas",
+ "description": "actor.canvas@1: an agent's live panel beside the conversation (ADR-059) — a board of a trip, a table of prices, a checklist of what is left. It is DATA: a list of blocks drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown (Chat, Surf, the Dock, Actor). There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it; an image is only a picture on openvibe.media; a link opens in a new tab with its host shown. A canvas acts only through the person: a button sends its label to the agent as the person's own message (action ask), and ticking a checklist item tells the agent which item changed; the agent's next steps go through its level and approvals like any other. VERSION only grows: a viewer ignores an older one, and the agent replaces the whole document, never part of it.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "canvas",
+ "id",
+ "title",
+ "version",
+ "blocks",
+ "updated_at"
+ ],
+ "properties": {
+ "canvas": {
+ "const": "actor.canvas@1"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^cnv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "title": {
+ "type": "string",
+ "maxLength": 120,
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Grows with every update; a viewer ignores an older version."
+ },
+ "agent_id": {
+ "type": "string",
+ "pattern": "^agt_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "The agent that draws it."
+ },
+ "thread": {
+ "type": "string",
+ "maxLength": 64,
+ "description": "The conversation it sits beside (Actor's task or chat id)."
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "blocks": {
+ "type": "array",
+ "maxItems": 60,
+ "items": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A heading.",
+ "required": [
+ "type",
+ "text"
+ ],
+ "properties": {
+ "type": {
+ "const": "heading"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 120,
+ "minLength": 1
+ },
+ "level": {
+ "type": "integer",
+ "enum": [
+ 1,
+ 2
+ ]
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Plain text; line breaks are kept, and nothing in it is markup.",
+ "required": [
+ "type",
+ "text"
+ ],
+ "properties": {
+ "type": {
+ "const": "text"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 4000,
+ "minLength": 1
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A list of short lines.",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "list"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "items": {
+ "type": "array",
+ "maxItems": 50,
+ "items": {
+ "type": "string",
+ "maxLength": 280,
+ "minLength": 1
+ }
+ },
+ "ordered": {
+ "type": "boolean"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "Items the person can tick; a tick tells the agent which item changed.",
+ "required": [
+ "type",
+ "items"
+ ],
+ "properties": {
+ "type": {
+ "const": "checklist"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "items": {
+ "type": "array",
+ "maxItems": 50,
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "id",
+ "text",
+ "done"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$"
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 280,
+ "minLength": 1
+ },
+ "done": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A table: up to 8 columns and 100 rows of text or numbers.",
+ "required": [
+ "type",
+ "columns",
+ "rows"
+ ],
+ "properties": {
+ "type": {
+ "const": "table"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "columns": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 8,
+ "items": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ }
+ },
+ "rows": {
+ "type": "array",
+ "maxItems": 100,
+ "items": {
+ "type": "array",
+ "maxItems": 8,
+ "items": {
+ "oneOf": [
+ {
+ "type": "string",
+ "maxLength": 200
+ },
+ {
+ "type": "number"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "One number that matters, with its label.",
+ "required": [
+ "type",
+ "label",
+ "value"
+ ],
+ "properties": {
+ "type": {
+ "const": "metric"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "label": {
+ "type": "string",
+ "maxLength": 60,
+ "minLength": 1
+ },
+ "value": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ },
+ "note": {
+ "type": "string",
+ "maxLength": 120
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A small bar or line chart; the renderer draws it, nothing is fetched.",
+ "required": [
+ "type",
+ "kind",
+ "series"
+ ],
+ "properties": {
+ "type": {
+ "const": "chart"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "kind": {
+ "type": "string",
+ "enum": [
+ "bar",
+ "line"
+ ]
+ },
+ "unit": {
+ "type": "string",
+ "maxLength": 12
+ },
+ "series": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 4,
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "name",
+ "points"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ },
+ "points": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 60,
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "x",
+ "y"
+ ],
+ "properties": {
+ "x": {
+ "type": "string",
+ "maxLength": 20,
+ "minLength": 1
+ },
+ "y": {
+ "type": "number"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A picture from OpenVibe.Media.",
+ "required": [
+ "type",
+ "src",
+ "alt"
+ ],
+ "properties": {
+ "type": {
+ "const": "image"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "src": {
+ "type": "string",
+ "pattern": "^https://openvibe\\.media/[A-Za-z0-9._~/%-]{1,1024}(\\?[A-Za-z0-9._~=&%-]{0,200})?$",
+ "description": "A picture on openvibe.media, and nowhere else."
+ },
+ "alt": {
+ "type": "string",
+ "maxLength": 200
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A link: it opens in a new tab and shows its host.",
+ "required": [
+ "type",
+ "href",
+ "text"
+ ],
+ "properties": {
+ "type": {
+ "const": "link"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "href": {
+ "type": "string",
+ "pattern": "^https://[^\\s\"'<>]{1,2048}$"
+ },
+ "text": {
+ "type": "string",
+ "maxLength": 120,
+ "minLength": 1
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "description": "A reply the person can send with one tap.",
+ "required": [
+ "type",
+ "label",
+ "action"
+ ],
+ "properties": {
+ "type": {
+ "const": "button"
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,39}$",
+ "description": "A stable id, so a viewer keeps its place when the canvas updates."
+ },
+ "label": {
+ "type": "string",
+ "maxLength": 40,
+ "minLength": 1
+ },
+ "action": {
+ "const": "ask",
+ "description": "The label goes to the agent as the person's own message. A button never acts by itself."
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
"actor.skill": {
"actor.skill": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "actor",
"owner": "actor",
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Actor API",
"title": "OpenVibe.Actor API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bench API",
"title": "OpenVibe.Bench API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"title": "OpenVibe.Blog API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe Connect API",
"title": "OpenVibe Connect API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Design API",
"title": "OpenVibe.Design API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Domains API",
"title": "OpenVibe.Domains API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Food API",
"title": "OpenVibe.Food API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Inventory API",
"title": "OpenVibe.Inventory API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Mail API",
"title": "OpenVibe.Mail API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.MediaHub API",
"title": "OpenVibe.MediaHub API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRestream API",
"title": "OpenRestream API",
- "version": "0.339.0",
- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Play API",
"title": "OpenVibe.Play API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Quest API",
"title": "OpenVibe.Quest API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Report API",
"title": "OpenVibe.Report API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Run API",
"title": "OpenVibe.Run API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Services API",
"title": "OpenVibe.Services API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Today API",
"title": "OpenVibe.Today API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Vision API",
"title": "OpenVibe.Vision API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Watch API",
"title": "OpenVibe.Watch API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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.339.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Work API",
"title": "OpenVibe.Work API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Zone API",
"title": "OpenVibe.Zone API",
- "version": "0.339.0",
- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.339.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
+ "version": "0.340.0",
+ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.340.0): each operation lists the capabilities it performs; a token for the 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"
@@ -301554,6 +301554,363 @@ export interface ActorSkillListing {
@@ -301554,6 +301554,363 @@ export interface ActorSkillListing {
retired_at?: string;
retired_at?: string;
}
}
+/** [email protected] (owner: actor) */
+/**
+ * actor.canvas@1: an agent's live panel beside the conversation (ADR-059) — a board of a trip, a table of prices, a checklist of what is left. It is DATA: a list of blocks drawn by one renderer (OpenVibe.Shared ov-canvas.js) wherever it is shown (Chat, Surf, the Dock, Actor). There is no HTML, no style, no script and no frame: text is plain and the renderer escapes it; an image is only a picture on openvibe.media; a link opens in a new tab with its host shown. A canvas acts only through the person: a button sends its label to the agent as the person's own message (action ask), and ticking a checklist item tells the agent which item changed; the agent's next steps go through its level and approvals like any other. VERSION only grows: a viewer ignores an older one, and the agent replaces the whole document, never part of it.
+ */
+export interface ActorCanvas {
+ canvas: "actor.canvas@1";
+ id: string;
+ title: string;
+ /**
+ * Grows with every update; a viewer ignores an older version.
+ */
+ version: number;
+ /**
+ * The agent that draws it.
+ */
+ agent_id?: string;
+ /**
+ * The conversation it sits beside (Actor's task or chat id).
+ */
+ thread?: string;
+ updated_at: string;
+ /**
+ * @maxItems 60
+ */
+ blocks: (
+ | {
+ type: "heading";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ text: string;
+ level?: 1 | 2;
+ }
+ | {
+ type: "text";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ text: string;
+ }
+ | {
+ type: "list";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ /**
+ * @maxItems 50
+ */
+ items: string[];
+ ordered?: boolean;
+ }
+ | {
+ type: "checklist";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ /**
+ * @maxItems 50
+ */
+ items: {
+ id: string;
+ text: string;
+ done: boolean;
+ }[];
+ }
+ | {
+ type: "table";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ /**
+ * @minItems 1
+ * @maxItems 8
+ */
+ columns:
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string];
+ /**
+ * @maxItems 100
+ */
+ rows:
+ | []
+ | [string | number]
+ | [string | number, string | number]
+ | [string | number, string | number, string | number]
+ | [string | number, string | number, string | number, string | number]
+ | [string | number, string | number, string | number, string | number, string | number]
+ | [string | number, string | number, string | number, string | number, string | number, string | number]
+ | [
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number
+ ]
+ | [
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number,
+ string | number
+ ][];
+ }
+ | {
+ type: "metric";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ label: string;
+ value: string;
+ note?: string;
+ }
+ | {
+ type: "chart";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ kind: "bar" | "line";
+ unit?: string;
+ /**
+ * @minItems 1
+ * @maxItems 4
+ */
+ series:
+ | [
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ }
+ ]
+ | [
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ },
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ }
+ ]
+ | [
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ },
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ },
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ }
+ ]
+ | [
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ },
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ },
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ },
+ {
+ name: string;
+ /**
+ * @minItems 1
+ * @maxItems 60
+ */
+ points: [
+ {
+ x: string;
+ y: number;
+ },
+ ...{
+ x: string;
+ y: number;
+ }[]
+ ];
+ }
+ ];
+ }
+ | {
+ type: "image";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ /**
+ * A picture on openvibe.media, and nowhere else.
+ */
+ src: string;
+ alt: string;
+ }
+ | {
+ type: "link";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ href: string;
+ text: string;
+ }
+ | {
+ type: "button";
+ /**
+ * A stable id, so a viewer keeps its place when the canvas updates.
+ */
+ id?: string;
+ label: string;
+ /**
+ * The label goes to the agent as the person's own message. A button never acts by itself.
+ */
+ action: "ask";
+ }
+ )[];
+}
+
/** [email protected] (owner: actor) */
/** [email protected] (owner: actor) */
/**
/**
* actor.skill@1: a skill, the document an agent loads to do one kind of job well (ADR-058). It follows the open Markdown-skill shape (a name, a one-line description, Markdown instructions) with what OpenVibe adds: a slug, a version, up to ten TEXT resources, and REQUIRES, what the skill may ask an agent to do. A skill GRANTS NOTHING: requires only declares; the agent's level and approvals decide every step (actor approvals, HO1), and a step of a kind the skill did not declare is a scan finding (actor.skill-listing@1). A v1 skill RUNS AS A PROMPT and nothing else: no code, no binary, no install recipe (a skill that runs code waits for a sandbox and a new major). DESCRIPTION is the only part an agent reads before it loads the skill (progressive disclosure), so it says when to use it. The INTEGRITY block is a sha256 over the canonical JSON of the document: it shows the file was not edited after it was written and says nothing about who wrote it, so the AUTHOR is a claim; the registry's listing is the only place a publisher is vouched for. The canonical JSON is the document's own fields, in this order: skill, slug, name, description, version, instructions, resources, requires, runs, license, author; an optional field that is absent or empty is left out; resources are [{ path, media_type, text }] in the document's order; requires is { kinds, apps, hosts } with empty lists left out; author is { subject } or { subject, name }; the value is the compact JSON of that object (no spaces). CREATED_AT is not hashed.
* actor.skill@1: a skill, the document an agent loads to do one kind of job well (ADR-058). It follows the open Markdown-skill shape (a name, a one-line description, Markdown instructions) with what OpenVibe adds: a slug, a version, up to ten TEXT resources, and REQUIRES, what the skill may ask an agent to do. A skill GRANTS NOTHING: requires only declares; the agent's level and approvals decide every step (actor approvals, HO1), and a step of a kind the skill did not declare is a scan finding (actor.skill-listing@1). A v1 skill RUNS AS A PROMPT and nothing else: no code, no binary, no install recipe (a skill that runs code waits for a sandbox and a new major). DESCRIPTION is the only part an agent reads before it loads the skill (progressive disclosure), so it says when to use it. The INTEGRITY block is a sha256 over the canonical JSON of the document: it shows the file was not edited after it was written and says nothing about who wrote it, so the AUTHOR is a claim; the registry's listing is the only place a publisher is vouched for. The canonical JSON is the document's own fields, in this order: skill, slug, name, description, version, instructions, resources, requires, runs, license, author; an optional field that is absent or empty is left out; resources are [{ path, media_type, text }] in the document's order; requires is { kinds, apps, hosts } with empty lists left out; author is { subject } or { subject, name }; the value is the compact JSON of that object (no spaces). CREATED_AT is not hashed.
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.339.0",
+ "version": "0.340.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",
@@ -1022,6 +1022,20 @@ sub(path.join(__dirname, 'changelog-history.test.js'));
@@ -1022,6 +1022,20 @@ sub(path.join(__dirname, 'changelog-history.test.js'));
ok(dangling.length === 0, `generated types reference undeclared names: ${dangling.join(', ')}`);
ok(dangling.length === 0, `generated types reference undeclared names: ${dangling.join(', ')}`);
}
}
+// ── actor.canvas@1 (ADR-059): data, never markup; a button only asks ─────────
+{
+ const c = contracts.schema('actor.canvas@1');
+ const types = c.properties.blocks.items.oneOf.map((b) => b.properties.type.const);
+ ok(!types.some((t) => /^(html|script|style|iframe|frame|embed|markup)$/i.test(t)), 'no canvas block is markup, a script, a style or a frame');
+ const button = c.properties.blocks.items.oneOf.find((b) => b.properties.type.const === 'button');
+ ok(button.properties.action.const === 'ask', 'a button only sends its label to the agent as the person\'s message');
+ const image = c.properties.blocks.items.oneOf.find((b) => b.properties.type.const === 'image');
+ ok(new RegExp(image.properties.src.pattern).test('https://openvibe.media/t/x.jpg') && !new RegExp(image.properties.src.pattern).test('https://tracker.example/p.png'), 'a picture comes from openvibe.media only');
+ const link = c.properties.blocks.items.oneOf.find((b) => b.properties.type.const === 'link');
+ ok(!new RegExp(link.properties.href.pattern).test('javascript:alert(1)') && !new RegExp(link.properties.href.pattern).test('http://x.y'), 'a link is https only');
+ ok(c.properties.blocks.maxItems === 60, 'at most 60 blocks');
+}
+
// ── actor.skill@1 and actor.skill-listing@1 (ADR-058) ───────────────────────
// ── actor.skill@1 and actor.skill-listing@1 (ADR-058) ───────────────────────
// A skill is a document: its integrity hash covers its canonical content (not a signature); it runs as a prompt
// A skill is a document: its integrity hash covers its canonical content (not a signature); it runs as a prompt
// only; it grants nothing, and what it may ask for is HO1's kinds; the listing's scan and curator travel with it.
// only; it grants nothing, and what it may ask for is HO1's kinds; the listing's scan and curator travel with it.