openvibers/openvibe.contracts Commits

Space's builder as the person's one agent: the builder API's contracts (0.321.0) (#331)

OP OpenVibers committed 6 days ago · fa806be801 · 74 files, +3601 −92

Space's "Describe it and OpenVibe AI builds it" becomes a task of the person's one
agent (plan 2026-10-22 section Z, stage Z1). These are the contracts of the API the
agent works through:

- space.build-space@1: one of a person's own spaces (id, slug, name, description,
  published, url, updated_at)
- space.build-list@1: { spaces } or { space }
- space.build-files@1: the space's files, each a path and its whole content
- space.build-create@1: the body of a request for a new space
- space.build-preview@1: where the space can be seen now, its file paths, whether it is live
- space.build-publish@1: pending, published or declined, with the request the person
  answers in the Dock

and the capabilities space.build.read, space.build.create, space.build.write and
space.build.publish. A first-party service names the person in X-OV-Subject; only that
person's own spaces are in reach. Additive: nothing that exists today changes shape.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex af4b0cfc..8e978327 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -1,5 +1,11 @@
# Changelog
++## 0.321.0 — 2026-11-07
++
++- Space's builder becomes a task of the person's one agent (plan 2026-10-22 §Z, stage Z1). Add the contracts of Space's builder API: `space.build-space@1` (one of a person's own spaces: its id, slug, name, description, whether it is published and where, and when it changed), `space.build-list@1` (`{ spaces }` or `{ space }`), `space.build-files@1` (the space's files, each a path and its whole content), `space.build-create@1` (the body of a request for a new space), `space.build-preview@1` (where the space can be seen now, its file paths, and whether it is live) and `space.build-publish@1` (`pending`, `published` or `declined`, with the request the person answers in the Dock).
++- Add the capabilities `space.build.read` (list and read the person's own spaces and their files), `space.build.create` (make a new space), `space.build.write` (write the files of one of them) and `space.build.publish` (ask to publish; the person answers before anything goes live). A first-party service names the person in `X-OV-Subject`, and only that person's own spaces are in reach.
++- Additive: nothing that exists today changes shape.
++
## 0.320.0 — 2026-11-07
- `frame.menu-card@1` items gain an optional `image`: `src` (https on the publishing site's own origin or an `openvibe.*` host, at most 400 characters), optional `w` and `h` (whole pixels, 16–1920) and an optional `alt` of at most 120 characters. Network keeps an image whose `src` passes the same host rule as the item's `url`, drops one from anywhere else, and passes it through in `GET /api/frame` so the Frame menu and Network's `/my` can draw a thumbnail.
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex 7c2a1b41..c25f9c4c 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -7767,6 +7767,60 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "space.build-space",
++ "version": "1.0.0",
++ "owner": "space",
++ "schema": "space/build-space.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "space.build-list",
++ "version": "1.0.0",
++ "owner": "space",
++ "schema": "space/build-list.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "space.build-files",
++ "version": "1.0.0",
++ "owner": "space",
++ "schema": "space/build-files.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "space.build-create",
++ "version": "1.0.0",
++ "owner": "space",
++ "schema": "space/build-create.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "space.build-preview",
++ "version": "1.0.0",
++ "owner": "space",
++ "schema": "space/build-preview.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "space.build-publish",
++ "version": "1.0.0",
++ "owner": "space",
++ "schema": "space/build-publish.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "space.deploy-create-request",
"version": "1.0.0",
ddiff --git a/contracts/space/build-create.v1.json b/contracts/space/build-create.v1.json
nnew file mode 100644
iindex 00000000..7849d1a3
---- /dev/null
++++ b/contracts/space/build-create.v1.json
@@@ -0,0 +1,20 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-create.v1.json",
++ "title": "SpaceBuildCreate",
++ "description": "space.build-create@1: the body of POST /api/v1/spaces, the agent asking Space for a new space of its own (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). It answers space.build-list@1 ({ space }). The name and the description are what the space shows; the space is made from Space's blank template and the agent fills its files.",
++ "type": "object",
++ "additionalProperties": false,
++ "properties": {
++ "name": {
++ "type": "string",
++ "maxLength": 40,
++ "description": "The space's name."
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 400,
++ "description": "What the space does, in a line."
++ }
++ }
++}
ddiff --git a/contracts/space/build-files.v1.json b/contracts/space/build-files.v1.json
nnew file mode 100644
iindex 00000000..22a9f209
---- /dev/null
++++ b/contracts/space/build-files.v1.json
@@@ -0,0 +1,38 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-files.v1.json",
++ "title": "SpaceBuildFiles",
++ "description": "space.build-files@1: the source files of one of a person's spaces, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/files answers { files }: every file of the space, its path and its whole content. The same shape is the body of PUT /api/v1/spaces/:id/files (space.build-write@1): the files to write, which replace the space's files as a whole.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "files"
++ ],
++ "properties": {
++ "files": {
++ "type": "array",
++ "maxItems": 20,
++ "items": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "path",
++ "content"
++ ],
++ "properties": {
++ "path": {
++ "type": "string",
++ "maxLength": 80,
++ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*(/[A-Za-z0-9][A-Za-z0-9._-]*){0,3}$",
++ "description": "The file's path inside the space: letters, digits, \".\", \"-\", \"_\", up to four folders."
++ },
++ "content": {
++ "type": "string",
++ "maxLength": 200000,
++ "description": "The file's whole content."
++ }
++ }
++ }
++ }
++ }
++}
ddiff --git a/contracts/space/build-list.v1.json b/contracts/space/build-list.v1.json
nnew file mode 100644
iindex 00000000..bf3d8ae5
---- /dev/null
++++ b/contracts/space/build-list.v1.json
@@@ -0,0 +1,35 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-list.v1.json",
++ "title": "SpaceBuildList",
++ "description": "space.build-list@1: the spaces of one person, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces answers { spaces }; GET /api/v1/spaces/:id answers { space }.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "spaces"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "spaces": {
++ "type": "array",
++ "items": {
++ "$ref": "build-space.v1.json"
++ }
++ }
++ }
++ },
++ {
++ "type": "object",
++ "required": [
++ "space"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "space": {
++ "$ref": "build-space.v1.json"
++ }
++ }
++ }
++ ]
++}
ddiff --git a/contracts/space/build-preview.v1.json b/contracts/space/build-preview.v1.json
nnew file mode 100644
iindex 00000000..b3e3d01f
---- /dev/null
++++ b/contracts/space/build-preview.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-preview.v1.json",
++ "title": "SpaceBuildPreview",
++ "description": "space.build-preview@1: where a person's space can be seen right now, as their agent sees it (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/preview answers { url, files, published }: the address to open (the editor with its live preview while the space is a draft, its own address once it is published), the paths of the files it is made of, and whether it is live.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "url",
++ "files",
++ "published"
++ ],
++ "properties": {
++ "url": {
++ "type": "string",
++ "format": "uri",
++ "description": "Where the space can be seen now."
++ },
++ "files": {
++ "type": "array",
++ "items": {
++ "type": "string",
++ "maxLength": 80
++ },
++ "description": "The paths of the files the space is made of."
++ },
++ "published": {
++ "type": "boolean"
++ }
++ }
++}
ddiff --git a/contracts/space/build-publish.v1.json b/contracts/space/build-publish.v1.json
nnew file mode 100644
iindex 00000000..90bdd324
---- /dev/null
++++ b/contracts/space/build-publish.v1.json
@@@ -0,0 +1,45 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-publish.v1.json",
++ "title": "SpaceBuildPublish",
++ "description": "space.build-publish@1: what happened when a person's agent asked to publish one of their spaces (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces/:id/publish asks to publish and answers { state: 'pending' } with the approval the person answers in the Dock; it never publishes without that answer. When the person approves, Space publishes and the step is { state: 'published', url }; when they decline, { state: 'declined' }.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "state"
++ ],
++ "properties": {
++ "state": {
++ "enum": [
++ "pending",
++ "published",
++ "declined"
++ ],
++ "description": "pending: the person must answer first. published: it is live at url. declined: the person said no."
++ },
++ "url": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "format": "uri",
++ "description": "Where it lives once it is published."
++ },
++ "approval_id": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "maxLength": 80,
++ "description": "The request the person answers in the Dock (its id)."
++ },
++ "reason": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "maxLength": 240,
++ "description": "Why it was refused, in one line a person can act on."
++ }
++ }
++}
ddiff --git a/contracts/space/build-space.v1.json b/contracts/space/build-space.v1.json
nnew file mode 100644
iindex 00000000..1877b588
---- /dev/null
++++ b/contracts/space/build-space.v1.json
@@@ -0,0 +1,49 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-space.v1.json",
++ "title": "SpaceBuildSpace",
++ "description": "space.build-space@1: one of a person's own spaces, as their agent sees it while it builds (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). The id, the slug it publishes under, its name and description, whether it is published and where, and when it last changed. Nothing about anyone else's space is ever in this shape.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "id",
++ "slug",
++ "name",
++ "published",
++ "url"
++ ],
++ "properties": {
++ "id": {
++ "type": "string",
++ "pattern": "^spc_[0-9A-HJKMNP-TV-Z]{26}$",
++ "description": "The space's id."
++ },
++ "slug": {
++ "type": "string",
++ "pattern": "^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){2,39}$",
++ "description": "The name it publishes under (<slug>.openvibe.website)."
++ },
++ "name": {
++ "type": "string",
++ "maxLength": 40
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 400
++ },
++ "published": {
++ "type": "boolean",
++ "description": "True while it is live at its own address."
++ },
++ "url": {
++ "type": "string",
++ "format": "uri",
++ "description": "Where it lives: its own address once published, the editor while it is a draft."
++ },
++ "updated_at": {
++ "type": "string",
++ "format": "date-time",
++ "description": "When it last changed."
++ }
++ }
++}
ddiff --git a/fixtures/space.build-create/invalid/too-long.json b/fixtures/space.build-create/invalid/too-long.json
nnew file mode 100644
iindex 00000000..bb068064
---- /dev/null
++++ b/fixtures/space.build-create/invalid/too-long.json
@@@ -0,0 +1,3 @@
++{
++ "name": "A name that is far longer than forty characters are allowed to be"
++}
ddiff --git a/fixtures/space.build-create/valid/plain.json b/fixtures/space.build-create/valid/plain.json
nnew file mode 100644
iindex 00000000..92a9e709
---- /dev/null
++++ b/fixtures/space.build-create/valid/plain.json
@@@ -0,0 +1,4 @@
++{
++ "name": "My Podcast",
++ "description": "A place for my episodes."
++}
ddiff --git a/fixtures/space.build-files/invalid/bad-path.json b/fixtures/space.build-files/invalid/bad-path.json
nnew file mode 100644
iindex 00000000..e92b153b
---- /dev/null
++++ b/fixtures/space.build-files/invalid/bad-path.json
@@@ -0,0 +1,5 @@
++{
++ "files": [
++ { "path": "../secrets.txt", "content": "no" }
++ ]
++}
ddiff --git a/fixtures/space.build-files/valid/two.json b/fixtures/space.build-files/valid/two.json
nnew file mode 100644
iindex 00000000..5fdfbb94
---- /dev/null
++++ b/fixtures/space.build-files/valid/two.json
@@@ -0,0 +1,6 @@
++{
++ "files": [
++ { "path": "index.html", "content": "<!doctype html><title>My Podcast</title>" },
++ { "path": "style.css", "content": "body { font: 16px system-ui; }" }
++ ]
++}
ddiff --git a/fixtures/space.build-list/invalid/unknown-field.json b/fixtures/space.build-list/invalid/unknown-field.json
nnew file mode 100644
iindex 00000000..3a45c17e
---- /dev/null
++++ b/fixtures/space.build-list/invalid/unknown-field.json
@@@ -0,0 +1,4 @@
++{
++ "spaces": [],
++ "other": 1
++}
ddiff --git a/fixtures/space.build-list/valid/many.json b/fixtures/space.build-list/valid/many.json
nnew file mode 100644
iindex 00000000..a49958e9
---- /dev/null
++++ b/fixtures/space.build-list/valid/many.json
@@@ -0,0 +1,13 @@
++{
++ "spaces": [
++ {
++ "id": "spc_01JAD2C3D4E5F6G7H8J9K0MNPQ",
++ "slug": "my-podcast",
++ "name": "My Podcast",
++ "description": "",
++ "published": false,
++ "url": "https://openvibe.space/spaces/my-podcast/edit",
++ "updated_at": "2026-11-07T09:30:00.000Z"
++ }
++ ]
++}
ddiff --git a/fixtures/space.build-list/valid/one.json b/fixtures/space.build-list/valid/one.json
nnew file mode 100644
iindex 00000000..f7cbaf3f
---- /dev/null
++++ b/fixtures/space.build-list/valid/one.json
@@@ -0,0 +1,9 @@
++{
++ "space": {
++ "id": "spc_01JAD2C3D4E5F6G7H8J9K0MNPQ",
++ "slug": "my-podcast",
++ "name": "My Podcast",
++ "published": false,
++ "url": "https://openvibe.space/spaces/my-podcast/edit"
++ }
++}
ddiff --git a/fixtures/space.build-preview/invalid/not-a-boolean.json b/fixtures/space.build-preview/invalid/not-a-boolean.json
nnew file mode 100644
iindex 00000000..8fd1d850
---- /dev/null
++++ b/fixtures/space.build-preview/invalid/not-a-boolean.json
@@@ -0,0 +1,5 @@
++{
++ "url": "https://openvibe.space/spaces/my-podcast/edit",
++ "files": [],
++ "published": "yes"
++}
ddiff --git a/fixtures/space.build-preview/valid/draft.json b/fixtures/space.build-preview/valid/draft.json
nnew file mode 100644
iindex 00000000..0c2b1f42
---- /dev/null
++++ b/fixtures/space.build-preview/valid/draft.json
@@@ -0,0 +1,5 @@
++{
++ "url": "https://openvibe.space/spaces/my-podcast/edit",
++ "files": ["index.html", "style.css"],
++ "published": false
++}
ddiff --git a/fixtures/space.build-publish/invalid/unknown-state.json b/fixtures/space.build-publish/invalid/unknown-state.json
nnew file mode 100644
iindex 00000000..79d4ffe6
---- /dev/null
++++ b/fixtures/space.build-publish/invalid/unknown-state.json
@@@ -0,0 +1,3 @@
++{
++ "state": "maybe"
++}
ddiff --git a/fixtures/space.build-publish/valid/pending.json b/fixtures/space.build-publish/valid/pending.json
nnew file mode 100644
iindex 00000000..d4014ad7
---- /dev/null
++++ b/fixtures/space.build-publish/valid/pending.json
@@@ -0,0 +1,6 @@
++{
++ "state": "pending",
++ "url": null,
++ "approval_id": "apr_01JAD2C3D4E5F6G7H8J9K0MNPQ",
++ "reason": null
++}
ddiff --git a/fixtures/space.build-space/invalid/bad-id.json b/fixtures/space.build-space/invalid/bad-id.json
nnew file mode 100644
iindex 00000000..df9146d2
---- /dev/null
++++ b/fixtures/space.build-space/invalid/bad-id.json
@@@ -0,0 +1,7 @@
++{
++ "id": "space-1",
++ "slug": "my-podcast",
++ "name": "My Podcast",
++ "published": false,
++ "url": "https://my-podcast.openvibe.website"
++}
ddiff --git a/fixtures/space.build-space/valid/one.json b/fixtures/space.build-space/valid/one.json
nnew file mode 100644
iindex 00000000..9635d7ee
---- /dev/null
++++ b/fixtures/space.build-space/valid/one.json
@@@ -0,0 +1,9 @@
++{
++ "id": "spc_01JAD2C3D4E5F6G7H8J9K0MNPQ",
++ "slug": "my-podcast",
++ "name": "My Podcast",
++ "description": "A place for my episodes.",
++ "published": true,
++ "url": "https://my-podcast.openvibe.website",
++ "updated_at": "2026-11-07T09:30:00.000Z"
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex a2de92ba..ba310e4c 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -87331,6 +87331,254 @@
]
}
},
++ "space.build-space": {
++ "version": "1.0.0",
++ "owner": "space",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-space.v1.json",
++ "title": "SpaceBuildSpace",
++ "description": "space.build-space@1: one of a person's own spaces, as their agent sees it while it builds (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). The id, the slug it publishes under, its name and description, whether it is published and where, and when it last changed. Nothing about anyone else's space is ever in this shape.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "id",
++ "slug",
++ "name",
++ "published",
++ "url"
++ ],
++ "properties": {
++ "id": {
++ "type": "string",
++ "pattern": "^spc_[0-9A-HJKMNP-TV-Z]{26}$",
++ "description": "The space's id."
++ },
++ "slug": {
++ "type": "string",
++ "pattern": "^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){2,39}$",
++ "description": "The name it publishes under (<slug>.openvibe.website)."
++ },
++ "name": {
++ "type": "string",
++ "maxLength": 40
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 400
++ },
++ "published": {
++ "type": "boolean",
++ "description": "True while it is live at its own address."
++ },
++ "url": {
++ "type": "string",
++ "format": "uri",
++ "description": "Where it lives: its own address once published, the editor while it is a draft."
++ },
++ "updated_at": {
++ "type": "string",
++ "format": "date-time",
++ "description": "When it last changed."
++ }
++ }
++ }
++ },
++ "space.build-list": {
++ "version": "1.0.0",
++ "owner": "space",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-list.v1.json",
++ "title": "SpaceBuildList",
++ "description": "space.build-list@1: the spaces of one person, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces answers { spaces }; GET /api/v1/spaces/:id answers { space }.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "spaces"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "spaces": {
++ "type": "array",
++ "items": {
++ "$ref": "build-space.v1.json"
++ }
++ }
++ }
++ },
++ {
++ "type": "object",
++ "required": [
++ "space"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "space": {
++ "$ref": "build-space.v1.json"
++ }
++ }
++ }
++ ]
++ }
++ },
++ "space.build-files": {
++ "version": "1.0.0",
++ "owner": "space",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-files.v1.json",
++ "title": "SpaceBuildFiles",
++ "description": "space.build-files@1: the source files of one of a person's spaces, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/files answers { files }: every file of the space, its path and its whole content. The same shape is the body of PUT /api/v1/spaces/:id/files (space.build-write@1): the files to write, which replace the space's files as a whole.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "files"
++ ],
++ "properties": {
++ "files": {
++ "type": "array",
++ "maxItems": 20,
++ "items": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "path",
++ "content"
++ ],
++ "properties": {
++ "path": {
++ "type": "string",
++ "maxLength": 80,
++ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*(/[A-Za-z0-9][A-Za-z0-9._-]*){0,3}$",
++ "description": "The file's path inside the space: letters, digits, \".\", \"-\", \"_\", up to four folders."
++ },
++ "content": {
++ "type": "string",
++ "maxLength": 200000,
++ "description": "The file's whole content."
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "space.build-create": {
++ "version": "1.0.0",
++ "owner": "space",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-create.v1.json",
++ "title": "SpaceBuildCreate",
++ "description": "space.build-create@1: the body of POST /api/v1/spaces, the agent asking Space for a new space of its own (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). It answers space.build-list@1 ({ space }). The name and the description are what the space shows; the space is made from Space's blank template and the agent fills its files.",
++ "type": "object",
++ "additionalProperties": false,
++ "properties": {
++ "name": {
++ "type": "string",
++ "maxLength": 40,
++ "description": "The space's name."
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 400,
++ "description": "What the space does, in a line."
++ }
++ }
++ }
++ },
++ "space.build-preview": {
++ "version": "1.0.0",
++ "owner": "space",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-preview.v1.json",
++ "title": "SpaceBuildPreview",
++ "description": "space.build-preview@1: where a person's space can be seen right now, as their agent sees it (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/preview answers { url, files, published }: the address to open (the editor with its live preview while the space is a draft, its own address once it is published), the paths of the files it is made of, and whether it is live.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "url",
++ "files",
++ "published"
++ ],
++ "properties": {
++ "url": {
++ "type": "string",
++ "format": "uri",
++ "description": "Where the space can be seen now."
++ },
++ "files": {
++ "type": "array",
++ "items": {
++ "type": "string",
++ "maxLength": 80
++ },
++ "description": "The paths of the files the space is made of."
++ },
++ "published": {
++ "type": "boolean"
++ }
++ }
++ }
++ },
++ "space.build-publish": {
++ "version": "1.0.0",
++ "owner": "space",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/space/build-publish.v1.json",
++ "title": "SpaceBuildPublish",
++ "description": "space.build-publish@1: what happened when a person's agent asked to publish one of their spaces (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces/:id/publish asks to publish and answers { state: 'pending' } with the approval the person answers in the Dock; it never publishes without that answer. When the person approves, Space publishes and the step is { state: 'published', url }; when they decline, { state: 'declined' }.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "state"
++ ],
++ "properties": {
++ "state": {
++ "enum": [
++ "pending",
++ "published",
++ "declined"
++ ],
++ "description": "pending: the person must answer first. published: it is live at url. declined: the person said no."
++ },
++ "url": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "format": "uri",
++ "description": "Where it lives once it is published."
++ },
++ "approval_id": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "maxLength": 80,
++ "description": "The request the person answers in the Dock (its id)."
++ },
++ "reason": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "maxLength": 240,
++ "description": "Why it was refused, in one line a person can act on."
++ }
++ }
++ }
++ },
"space.deploy-create-request": {
"version": "1.0.0",
"owner": "space",
ddiff --git a/generated/openapi/actor.json b/generated/openapi/actor.json
iindex ff60d2b0..3eca5c19 100644
---- a/generated/openapi/actor.json
++++ b/generated/openapi/actor.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Actor API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex b2a70003..144d28e4 100644
---- a/generated/openapi/ai.json
++++ b/generated/openapi/ai.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.AI API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/bench.json b/generated/openapi/bench.json
iindex f835b6ef..8d7d9caf 100644
---- a/generated/openapi/bench.json
++++ b/generated/openapi/bench.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bench API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/billing.json b/generated/openapi/billing.json
iindex e9c55875..efb9a19e 100644
---- a/generated/openapi/billing.json
++++ b/generated/openapi/billing.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Billing API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/blog.json b/generated/openapi/blog.json
iindex 7126c110..1b2aa486 100644
---- a/generated/openapi/blog.json
++++ b/generated/openapi/blog.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Blog API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/bot.json b/generated/openapi/bot.json
iindex 2843f89e..6678bdb0 100644
---- a/generated/openapi/bot.json
++++ b/generated/openapi/bot.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bot API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/chat.json b/generated/openapi/chat.json
iindex 5ad5dd9a..a4794fd0 100644
---- a/generated/openapi/chat.json
++++ b/generated/openapi/chat.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Chat API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/codes.json b/generated/openapi/codes.json
iindex 74c69de7..2c04aca2 100644
---- a/generated/openapi/codes.json
++++ b/generated/openapi/codes.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Codes API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/community.json b/generated/openapi/community.json
iindex 797f6983..448c3de9 100644
---- a/generated/openapi/community.json
++++ b/generated/openapi/community.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Community API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/connect.json b/generated/openapi/connect.json
iindex 39172fb9..606e8fb7 100644
---- a/generated/openapi/connect.json
++++ b/generated/openapi/connect.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe Connect API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/coupons.json b/generated/openapi/coupons.json
iindex bf7e7b25..216b5f51 100644
---- a/generated/openapi/coupons.json
++++ b/generated/openapi/coupons.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Coupons API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/deals.json b/generated/openapi/deals.json
iindex 6d2c363c..f9fc8b82 100644
---- a/generated/openapi/deals.json
++++ b/generated/openapi/deals.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Deals API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/design.json b/generated/openapi/design.json
iindex 8c882494..6b06073a 100644
---- a/generated/openapi/design.json
++++ b/generated/openapi/design.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Design API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/domains.json b/generated/openapi/domains.json
iindex 2c9f6a2a..bb54ef36 100644
---- a/generated/openapi/domains.json
++++ b/generated/openapi/domains.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Domains API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/events.json b/generated/openapi/events.json
iindex c7db99bf..63d47428 100644
---- a/generated/openapi/events.json
++++ b/generated/openapi/events.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Events API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/food.json b/generated/openapi/food.json
iindex b723f543..ea168f65 100644
---- a/generated/openapi/food.json
++++ b/generated/openapi/food.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Food API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/games.json b/generated/openapi/games.json
iindex 684f1377..bfe22c31 100644
---- a/generated/openapi/games.json
++++ b/generated/openapi/games.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Games API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/host.json b/generated/openapi/host.json
iindex 68cdd1c1..fdfe5f72 100644
---- a/generated/openapi/host.json
++++ b/generated/openapi/host.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Host API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/index.json b/generated/openapi/index.json
iindex aa5a699c..2af4b2f6 100644
---- a/generated/openapi/index.json
++++ b/generated/openapi/index.json
@@@ -236,8 +236,8 @@
"service": "space",
"name": "OpenVibe.Space",
"origin": "https://openvibe.space",
-- "operations": 37,
-- "capabilities": 6
++ "operations": 44,
++ "capabilities": 10
},
{
"service": "tips",
ddiff --git a/generated/openapi/inventory.json b/generated/openapi/inventory.json
iindex c586805e..018d88d2 100644
---- a/generated/openapi/inventory.json
++++ b/generated/openapi/inventory.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Inventory API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex 6bf0e226..e1bbb364 100644
---- a/generated/openapi/live.json
++++ b/generated/openapi/live.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Live API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/media-hub.json b/generated/openapi/media-hub.json
iindex 653505a4..db676712 100644
---- a/generated/openapi/media-hub.json
++++ b/generated/openapi/media-hub.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.MediaHub API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/media.json b/generated/openapi/media.json
iindex 283176e3..d4beedab 100644
---- a/generated/openapi/media.json
++++ b/generated/openapi/media.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Media API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/network.json b/generated/openapi/network.json
iindex 32073139..1fa85970 100644
---- a/generated/openapi/network.json
++++ b/generated/openapi/network.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Network API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex f0747d04..3f520fc4 100644
---- a/generated/openapi/news.json
++++ b/generated/openapi/news.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.News API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/openre.json b/generated/openapi/openre.json
iindex 77e9283d..54e3fc00 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRestream API",
-- "version": "0.320.0",
-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/play.json b/generated/openapi/play.json
iindex f8b9157b..3c570f3d 100644
---- a/generated/openapi/play.json
++++ b/generated/openapi/play.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Play API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/quest.json b/generated/openapi/quest.json
iindex 0ae34c89..d1b272b1 100644
---- a/generated/openapi/quest.json
++++ b/generated/openapi/quest.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Quest API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/report.json b/generated/openapi/report.json
iindex fae44f20..5264f59d 100644
---- a/generated/openapi/report.json
++++ b/generated/openapi/report.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Report API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/reviews.json b/generated/openapi/reviews.json
iindex 74276d15..05998c74 100644
---- a/generated/openapi/reviews.json
++++ b/generated/openapi/reviews.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Reviews API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/run.json b/generated/openapi/run.json
iindex 2e10abc2..ba292627 100644
---- a/generated/openapi/run.json
++++ b/generated/openapi/run.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Run API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/search.json b/generated/openapi/search.json
iindex c669c6e7..bca2676a 100644
---- a/generated/openapi/search.json
++++ b/generated/openapi/search.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Search API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/services.json b/generated/openapi/services.json
iindex 152140fe..602dffad 100644
---- a/generated/openapi/services.json
++++ b/generated/openapi/services.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Services API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/sources.json b/generated/openapi/sources.json
iindex 685a7da1..90c850fd 100644
---- a/generated/openapi/sources.json
++++ b/generated/openapi/sources.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Sources API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/space.json b/generated/openapi/space.json
iindex 5100316f..686cf1ae 100644
---- a/generated/openapi/space.json
++++ b/generated/openapi/space.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Space API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
@@@ -2345,6 +2345,394 @@
}
}
}
++ },
++ "/api/v1/spaces": {
++ "get": {
++ "operationId": "get_api_v1_spaces",
++ "summary": "Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent).",
++ "description": "**space.build.read** (first-party): Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent). GET /api/v1/spaces lists the person's spaces, GET /api/v1/spaces/:id reads one, GET /api/v1/spaces/:id/files reads its files, GET /api/v1/spaces/:id/preview says where it can be seen. A first-party service names the person in X-OV-Subject; Space reads only that person's own spaces, and another person's space is the same 404 as one that does not exist.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.read"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.read"
++ ]
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-list.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ },
++ "post": {
++ "operationId": "post_api_v1_spaces",
++ "summary": "Make one of a person's own spaces, as their agent (OpenVibe.Actor) builds it (plan 2026-10-22 §Z stage Z1).",
++ "description": "**space.build.create** (first-party): Make one of a person's own spaces, as their agent (OpenVibe.Actor) builds it (plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces makes a new space of the person named in X-OV-Subject, from Space's blank template; the agent then fills its files with space.build.write.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.create"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.create"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-create.v1"
++ }
++ }
++ }
++ },
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-list.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/api/v1/spaces/{id}": {
++ "get": {
++ "operationId": "get_api_v1_spaces_id",
++ "summary": "Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent).",
++ "description": "**space.build.read** (first-party): Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent). GET /api/v1/spaces lists the person's spaces, GET /api/v1/spaces/:id reads one, GET /api/v1/spaces/:id/files reads its files, GET /api/v1/spaces/:id/preview says where it can be seen. A first-party service names the person in X-OV-Subject; Space reads only that person's own spaces, and another person's space is the same 404 as one that does not exist.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.read"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.read"
++ ]
++ }
++ ],
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-list.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/api/v1/spaces/{id}/files": {
++ "get": {
++ "operationId": "get_api_v1_spaces_id_files",
++ "summary": "Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent).",
++ "description": "**space.build.read** (first-party): Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent). GET /api/v1/spaces lists the person's spaces, GET /api/v1/spaces/:id reads one, GET /api/v1/spaces/:id/files reads its files, GET /api/v1/spaces/:id/preview says where it can be seen. A first-party service names the person in X-OV-Subject; Space reads only that person's own spaces, and another person's space is the same 404 as one that does not exist.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.read"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.read"
++ ]
++ }
++ ],
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-list.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ },
++ "put": {
++ "operationId": "put_api_v1_spaces_id_files",
++ "summary": "Write the files of one of a person's own spaces, as their agent (OpenVibe.Actor) builds it (plan 2026-10-22 §Z stage Z1).",
++ "description": "**space.build.write** (first-party): Write the files of one of a person's own spaces, as their agent (OpenVibe.Actor) builds it (plan 2026-10-22 §Z stage Z1). PUT /api/v1/spaces/:id/files replaces the space's files with the ones in the body. Every write is audited like Space's own editor writes are, and the space's own limits (files, bytes) are the same ones.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.write"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.write"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-files.v1"
++ }
++ }
++ }
++ },
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-files.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/api/v1/spaces/{id}/preview": {
++ "get": {
++ "operationId": "get_api_v1_spaces_id_preview",
++ "summary": "Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent).",
++ "description": "**space.build.read** (first-party): Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent). GET /api/v1/spaces lists the person's spaces, GET /api/v1/spaces/:id reads one, GET /api/v1/spaces/:id/files reads its files, GET /api/v1/spaces/:id/preview says where it can be seen. A first-party service names the person in X-OV-Subject; Space reads only that person's own spaces, and another person's space is the same 404 as one that does not exist.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.read"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.read"
++ ]
++ }
++ ],
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-list.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/api/v1/spaces/{id}/publish": {
++ "post": {
++ "operationId": "post_api_v1_spaces_id_publish",
++ "summary": "Ask to publish one of a person's own spaces, as their agent (OpenVibe.Actor) built it (plan 2026-10-22 §Z stage Z1).",
++ "description": "**space.build.publish** (first-party): Ask to publish one of a person's own spaces, as their agent (OpenVibe.Actor) built it (plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces/:id/publish asks and answers { state: 'pending' } with the request the person answers in the Dock; Space never publishes without that answer, and the agent is told to wait. The person's answer reaches Space through POST /api/v1/agent/approvals/:id/decide.",
++ "tags": [
++ "space.build"
++ ],
++ "x-openvibe-capabilities": [
++ "space.build.publish"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "standard",
++ "security": [
++ {
++ "openvibeToken": [
++ "space.build.publish"
++ ]
++ }
++ ],
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/space.build-publish.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
}
},
"components": {
@@@ -2814,6 +3202,183 @@
}
]
},
++ "space.build-create.v1": {
++ "title": "SpaceBuildCreate",
++ "description": "space.build-create@1: the body of POST /api/v1/spaces, the agent asking Space for a new space of its own (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). It answers space.build-list@1 ({ space }). The name and the description are what the space shows; the space is made from Space's blank template and the agent fills its files.",
++ "type": "object",
++ "additionalProperties": false,
++ "properties": {
++ "name": {
++ "type": "string",
++ "maxLength": 40,
++ "description": "The space's name."
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 400,
++ "description": "What the space does, in a line."
++ }
++ }
++ },
++ "space.build-files.v1": {
++ "title": "SpaceBuildFiles",
++ "description": "space.build-files@1: the source files of one of a person's spaces, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/files answers { files }: every file of the space, its path and its whole content. The same shape is the body of PUT /api/v1/spaces/:id/files (space.build-write@1): the files to write, which replace the space's files as a whole.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "files"
++ ],
++ "properties": {
++ "files": {
++ "type": "array",
++ "maxItems": 20,
++ "items": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "path",
++ "content"
++ ],
++ "properties": {
++ "path": {
++ "type": "string",
++ "maxLength": 80,
++ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*(/[A-Za-z0-9][A-Za-z0-9._-]*){0,3}$",
++ "description": "The file's path inside the space: letters, digits, \".\", \"-\", \"_\", up to four folders."
++ },
++ "content": {
++ "type": "string",
++ "maxLength": 200000,
++ "description": "The file's whole content."
++ }
++ }
++ }
++ }
++ }
++ },
++ "space.build-list.v1": {
++ "title": "SpaceBuildList",
++ "description": "space.build-list@1: the spaces of one person, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces answers { spaces }; GET /api/v1/spaces/:id answers { space }.",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "spaces"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "spaces": {
++ "type": "array",
++ "items": {
++ "$ref": "#/components/schemas/space.build-space.v1"
++ }
++ }
++ }
++ },
++ {
++ "type": "object",
++ "required": [
++ "space"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "space": {
++ "$ref": "#/components/schemas/space.build-space.v1"
++ }
++ }
++ }
++ ]
++ },
++ "space.build-publish.v1": {
++ "title": "SpaceBuildPublish",
++ "description": "space.build-publish@1: what happened when a person's agent asked to publish one of their spaces (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces/:id/publish asks to publish and answers { state: 'pending' } with the approval the person answers in the Dock; it never publishes without that answer. When the person approves, Space publishes and the step is { state: 'published', url }; when they decline, { state: 'declined' }.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "state"
++ ],
++ "properties": {
++ "state": {
++ "enum": [
++ "pending",
++ "published",
++ "declined"
++ ],
++ "description": "pending: the person must answer first. published: it is live at url. declined: the person said no."
++ },
++ "url": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "format": "uri",
++ "description": "Where it lives once it is published."
++ },
++ "approval_id": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "maxLength": 80,
++ "description": "The request the person answers in the Dock (its id)."
++ },
++ "reason": {
++ "type": [
++ "string",
++ "null"
++ ],
++ "maxLength": 240,
++ "description": "Why it was refused, in one line a person can act on."
++ }
++ }
++ },
++ "space.build-space.v1": {
++ "title": "SpaceBuildSpace",
++ "description": "space.build-space@1: one of a person's own spaces, as their agent sees it while it builds (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). The id, the slug it publishes under, its name and description, whether it is published and where, and when it last changed. Nothing about anyone else's space is ever in this shape.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "id",
++ "slug",
++ "name",
++ "published",
++ "url"
++ ],
++ "properties": {
++ "id": {
++ "type": "string",
++ "pattern": "^spc_[0-9A-HJKMNP-TV-Z]{26}$",
++ "description": "The space's id."
++ },
++ "slug": {
++ "type": "string",
++ "pattern": "^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){2,39}$",
++ "description": "The name it publishes under (<slug>.openvibe.website)."
++ },
++ "name": {
++ "type": "string",
++ "maxLength": 40
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 400
++ },
++ "published": {
++ "type": "boolean",
++ "description": "True while it is live at its own address."
++ },
++ "url": {
++ "type": "string",
++ "format": "uri",
++ "description": "Where it lives: its own address once published, the editor while it is a draft."
++ },
++ "updated_at": {
++ "type": "string",
++ "format": "date-time",
++ "description": "When it last changed."
++ }
++ }
++ },
"space.deploy-create-request.v1": {
"title": "SpaceDeployCreateRequest",
"description": "space.deploy-create-request@1: bodies of space.deploy.create on OpenVibe.Space (a deployer or above of the project; an app principal added as deployer can deploy from CI). POST /api/v1/sites/:id/deploys uploads a deploy: the raw body is a tar or tar.gz archive (Content-Type application/gzip, application/x-gzip, application/x-tar or application/octet-stream), or multipart/form-data with archive=<one archive> or files=<file>… (each part's filename is its path); optional fields activate=1, root=<subdirectory to deploy> and strip=folder (removes a shared first segment) also work as query parameters. It is validated (path traversal, links, special and hidden files, server-side code, file types, sizes and quotas) and never executed; a refusal is a problem whose extra carries the failed deploy_id and its log (413 upload.too_large, quota.storage; 422 validation codes; 429 quota.deploys_per_day; 403 site.taken_down; 503 upload.busy; 507 storage.host_full). POST /api/v1/deploys/:id/activate { expected_active? } and POST /api/v1/sites/:id/rollback { deploy_id?, expected_active? } switch the site's pointer in one step (rollback without deploy_id goes to the deploy active before; 409 deploy.not_ready, site.active_changed when expected_active is stale, deploy.no_previous). GET /api/v1/sites/:id/deploys, /deploys/:id and /deploys/:id/log take no body.",
ddiff --git a/generated/openapi/tips.json b/generated/openapi/tips.json
iindex 3a0bf2b2..63c90855 100644
---- a/generated/openapi/tips.json
++++ b/generated/openapi/tips.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tips API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/today.json b/generated/openapi/today.json
iindex 21f34296..ede2d3b0 100644
---- a/generated/openapi/today.json
++++ b/generated/openapi/today.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Today API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/tools.json b/generated/openapi/tools.json
iindex 783e6e27..a35d5bf6 100644
---- a/generated/openapi/tools.json
++++ b/generated/openapi/tools.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tools API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/trade.json b/generated/openapi/trade.json
iindex 47c93aeb..4d767042 100644
---- a/generated/openapi/trade.json
++++ b/generated/openapi/trade.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Trade API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/vip.json b/generated/openapi/vip.json
iindex 2ab03f1c..239389e2 100644
---- a/generated/openapi/vip.json
++++ b/generated/openapi/vip.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.VIP API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/vision.json b/generated/openapi/vision.json
iindex dc205668..9c997ff0 100644
---- a/generated/openapi/vision.json
++++ b/generated/openapi/vision.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Vision API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/watch.json b/generated/openapi/watch.json
iindex a36f949f..c73c8df3 100644
---- a/generated/openapi/watch.json
++++ b/generated/openapi/watch.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Watch API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/wiki.json b/generated/openapi/wiki.json
iindex a8728142..c8a9f0c6 100644
---- a/generated/openapi/wiki.json
++++ b/generated/openapi/wiki.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Wiki API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/work.json b/generated/openapi/work.json
iindex 8658dd81..810df1c0 100644
---- a/generated/openapi/work.json
++++ b/generated/openapi/work.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Work API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/openapi/zone.json b/generated/openapi/zone.json
iindex 284e618c..7b1f8a93 100644
---- a/generated/openapi/zone.json
++++ b/generated/openapi/zone.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Zone API",
-- "version": "0.320.0",
-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.320.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.321.0",
++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.321.0): each operation lists the capabilities it performs; a token for the 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"
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex b9fc4dde..0882eeb0 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -269471,6 +269471,2253 @@ export type FoodRecipeResult =
];
};
++/** [email protected] (owner: space) */
++/**
++ * space.build-space@1: one of a person's own spaces, as their agent sees it while it builds (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). The id, the slug it publishes under, its name and description, whether it is published and where, and when it last changed. Nothing about anyone else's space is ever in this shape.
++ */
++export interface SpaceBuildSpace {
++ /**
++ * The space's id.
++ */
++ id: string;
++ /**
++ * The name it publishes under (<slug>.openvibe.website).
++ */
++ slug: string;
++ name: string;
++ description?: string;
++ /**
++ * True while it is live at its own address.
++ */
++ published: boolean;
++ /**
++ * Where it lives: its own address once published, the editor while it is a draft.
++ */
++ url: string;
++ /**
++ * When it last changed.
++ */
++ updated_at?: string;
++}
++
++/** [email protected] (owner: space) */
++/**
++ * space.build-list@1: the spaces of one person, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces answers { spaces }; GET /api/v1/spaces/:id answers { space }.
++ */
++export type SpaceBuildList =
++ | {
++ spaces: SpaceBuildSpace[];
++ }
++ | {
++ space: SpaceBuildSpace;
++ };
++
++/** [email protected] (owner: space) */
++/**
++ * space.build-files@1: the source files of one of a person's spaces, as their agent sees them (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/files answers { files }: every file of the space, its path and its whole content. The same shape is the body of PUT /api/v1/spaces/:id/files (space.build-write@1): the files to write, which replace the space's files as a whole.
++ */
++export interface SpaceBuildFiles {
++ /**
++ * @maxItems 20
++ */
++ files:
++ | []
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ]
++ | [
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ },
++ {
++ /**
++ * The file's path inside the space: letters, digits, ".", "-", "_", up to four folders.
++ */
++ path: string;
++ /**
++ * The file's whole content.
++ */
++ content: string;
++ }
++ ];
++}
++
++/** [email protected] (owner: space) */
++/**
++ * space.build-create@1: the body of POST /api/v1/spaces, the agent asking Space for a new space of its own (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). It answers space.build-list@1 ({ space }). The name and the description are what the space shows; the space is made from Space's blank template and the agent fills its files.
++ */
++export interface SpaceBuildCreate {
++ /**
++ * The space's name.
++ */
++ name?: string;
++ /**
++ * What the space does, in a line.
++ */
++ description?: string;
++}
++
++/** [email protected] (owner: space) */
++/**
++ * space.build-preview@1: where a person's space can be seen right now, as their agent sees it (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). GET /api/v1/spaces/:id/preview answers { url, files, published }: the address to open (the editor with its live preview while the space is a draft, its own address once it is published), the paths of the files it is made of, and whether it is live.
++ */
++export interface SpaceBuildPreview {
++ /**
++ * Where the space can be seen now.
++ */
++ url: string;
++ /**
++ * The paths of the files the space is made of.
++ */
++ files: string[];
++ published: boolean;
++}
++
++/** [email protected] (owner: space) */
++/**
++ * space.build-publish@1: what happened when a person's agent asked to publish one of their spaces (OpenVibe.Space's builder API; plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces/:id/publish asks to publish and answers { state: 'pending' } with the approval the person answers in the Dock; it never publishes without that answer. When the person approves, Space publishes and the step is { state: 'published', url }; when they decline, { state: 'declined' }.
++ */
++export interface SpaceBuildPublish {
++ /**
++ * pending: the person must answer first. published: it is live at url. declined: the person said no.
++ */
++ state: "pending" | "published" | "declined";
++ /**
++ * Where it lives once it is published.
++ */
++ url?: string | null;
++ /**
++ * The request the person answers in the Dock (its id).
++ */
++ approval_id?: string | null;
++ /**
++ * Why it was refused, in one line a person can act on.
++ */
++ reason?: string | null;
++}
++
/** [email protected] (owner: space) */
/**
* space.deploy-create-request@1: bodies of space.deploy.create on OpenVibe.Space (a deployer or above of the project; an app principal added as deployer can deploy from CI). POST /api/v1/sites/:id/deploys uploads a deploy: the raw body is a tar or tar.gz archive (Content-Type application/gzip, application/x-gzip, application/x-tar or application/octet-stream), or multipart/form-data with archive=<one archive> or files=<file>… (each part's filename is its path); optional fields activate=1, root=<subdirectory to deploy> and strip=folder (removes a shared first segment) also work as query parameters. It is validated (path traversal, links, special and hidden files, server-side code, file types, sizes and quotas) and never executed; a refusal is a problem whose extra carries the failed deploy_id and its log (413 upload.too_large, quota.storage; 422 validation codes; 429 quota.deploys_per_day; 403 site.taken_down; 503 upload.busy; 507 storage.host_full). POST /api/v1/deploys/:id/activate { expected_active? } and POST /api/v1/sites/:id/rollback { deploy_id?, expected_active? } switch the site's pointer in one step (rollback without deploy_id goes to the deploy active before; 409 deploy.not_ready, site.active_changed when expected_active is stale, deploy.no_previous). GET /api/v1/sites/:id/deploys, /deploys/:id and /deploys/:id/log take no body.
ddiff --git a/manifests/capabilities/space.build.create.json b/manifests/capabilities/space.build.create.json
nnew file mode 100644
iindex 00000000..9c3ea467
---- /dev/null
++++ b/manifests/capabilities/space.build.create.json
@@@ -0,0 +1,21 @@
++{
++ "id": "space.build.create",
++ "version": "1.0",
++ "owner": "space",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Make one of a person's own spaces, as their agent (OpenVibe.Actor) builds it (plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces makes a new space of the person named in X-OV-Subject, from Space's blank template; the agent then fills its files with space.build.write.",
++ "permissions": [
++ "spaces:write"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "standard",
++ "events": [],
++ "implementedBy": [
++ "POST /api/v1/spaces"
++ ],
++ "inputSchema": "space.build-create@1",
++ "outputSchema": "space.build-list@1"
++}
ddiff --git a/manifests/capabilities/space.build.publish.json b/manifests/capabilities/space.build.publish.json
nnew file mode 100644
iindex 00000000..cc455fd5
---- /dev/null
++++ b/manifests/capabilities/space.build.publish.json
@@@ -0,0 +1,22 @@
++{
++ "id": "space.build.publish",
++ "version": "1.0",
++ "owner": "space",
++ "status": "active",
++ "visibility": "first-party",
++ "sensitive": true,
++ "description": "Ask to publish one of a person's own spaces, as their agent (OpenVibe.Actor) built it (plan 2026-10-22 §Z stage Z1). POST /api/v1/spaces/:id/publish asks and answers { state: 'pending' } with the request the person answers in the Dock; Space never publishes without that answer, and the agent is told to wait. The person's answer reaches Space through POST /api/v1/agent/approvals/:id/decide.",
++ "permissions": [
++ "spaces:publish"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "standard",
++ "events": [],
++ "implementedBy": [
++ "POST /api/v1/spaces/:id/publish"
++ ],
++ "inputSchema": "common.no-body@1",
++ "outputSchema": "space.build-publish@1"
++}
ddiff --git a/manifests/capabilities/space.build.read.json b/manifests/capabilities/space.build.read.json
nnew file mode 100644
iindex 00000000..c77f2a2f
---- /dev/null
++++ b/manifests/capabilities/space.build.read.json
@@@ -0,0 +1,24 @@
++{
++ "id": "space.build.read",
++ "version": "1.0",
++ "owner": "space",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Read a person's own spaces and their source files, as their agent (OpenVibe.Actor) works on them (plan 2026-10-22 §Z stage Z1: Space's builder becomes a task of the person's one agent). GET /api/v1/spaces lists the person's spaces, GET /api/v1/spaces/:id reads one, GET /api/v1/spaces/:id/files reads its files, GET /api/v1/spaces/:id/preview says where it can be seen. A first-party service names the person in X-OV-Subject; Space reads only that person's own spaces, and another person's space is the same 404 as one that does not exist.",
++ "permissions": [
++ "spaces:read"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "standard",
++ "events": [],
++ "implementedBy": [
++ "GET /api/v1/spaces",
++ "GET /api/v1/spaces/:id",
++ "GET /api/v1/spaces/:id/files",
++ "GET /api/v1/spaces/:id/preview"
++ ],
++ "inputSchema": "common.no-body@1",
++ "outputSchema": "space.build-list@1"
++}
ddiff --git a/manifests/capabilities/space.build.write.json b/manifests/capabilities/space.build.write.json
nnew file mode 100644
iindex 00000000..7a4ee0a9
---- /dev/null
++++ b/manifests/capabilities/space.build.write.json
@@@ -0,0 +1,21 @@
++{
++ "id": "space.build.write",
++ "version": "1.0",
++ "owner": "space",
++ "status": "active",
++ "visibility": "first-party",
++ "description": "Write the files of one of a person's own spaces, as their agent (OpenVibe.Actor) builds it (plan 2026-10-22 §Z stage Z1). PUT /api/v1/spaces/:id/files replaces the space's files with the ones in the body. Every write is audited like Space's own editor writes are, and the space's own limits (files, bytes) are the same ones.",
++ "permissions": [
++ "spaces:write"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
++ "quotaClass": "standard",
++ "events": [],
++ "implementedBy": [
++ "PUT /api/v1/spaces/:id/files"
++ ],
++ "inputSchema": "space.build-files@1",
++ "outputSchema": "space.build-files@1"
++}
ddiff --git a/manifests/services/space.json b/manifests/services/space.json
iindex 19536938..88dcc500 100644
---- a/manifests/services/space.json
++++ b/manifests/services/space.json
@@@ -71,7 +71,11 @@
"space.domain.manage",
"space.site.config",
"space.resource.read",
-- "space.resource.control"
++ "space.resource.control",
++ "space.build.read",
++ "space.build.create",
++ "space.build.write",
++ "space.build.publish"
],
"eventsProduced": [
"space.deploy.created",
ddiff --git a/package.json b/package.json
iindex ff2807f8..0b53f40f 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.320.0",
++ "version": "0.321.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",