openvibers/openvibe.contracts Commits

Contracts 0.142.0: Games script mods (games.script.run and four bindings) (#98)

OP OpenVibers committed 11 Oct 2026 · 025e7f29f2 · 73 files, +1194 −74

Games milestone M3 (scripted mods, Games PR to follow): `games.script.run` plus the per-mod script bindings `games.players.read`, `games.player.message`, `games.world.emit` and `games.storage.kv`, all active. Each has input and output schemas (`games.script-call@1`, `games.script-call-result@1`, `games.script-players@1`, `games.script-message@1`, `games.script-intent@1`, `games.script-storage-request@1`, `games.script-storage-result@1`) with fixtures.

A binding is absent from a script unless its install was granted it. `games.mod.manage` adds `POST /api/v1/mods/:id/reload` (hot reload, storage kept).

Suite: 18695 checks passed. compat vs v0.141.0: no breaking changes.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 1dfca2a6..afc8802f 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,15 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
++## 0.142.0 — 2026-10-11
++
++- Games milestone M3 (scripted mods): `games.script.run` and the per-mod script bindings `games.players.read`,
++ `games.player.message`, `games.world.emit` and `games.storage.kv` (active). A binding is absent from a script unless its
++ install was granted it; grants travel in the def-set digest. Their schemas: `games.script-call@1`,
++ `games.script-call-result@1`, `games.script-players@1`, `games.script-message@1`, `games.script-intent@1`,
++ `games.script-storage-request@1` and `games.script-storage-result@1`.
++- `games.mod.manage` adds `POST /api/v1/mods/:id/reload` (hot reload of a script mod, storage kept).
++
## 0.141.0 — 2026-10-11
- `run`: a `site` block with `tld: run` (openvibe.run serves its own front page since Run#28) and `exposure` live with
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex ecf92df1..50f5add7 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -4486,6 +4486,69 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "games.script-call",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-call.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "games.script-call-result",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-call-result.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "games.script-players",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-players.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "games.script-message",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-message.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "games.script-intent",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-intent.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "games.script-storage-request",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-storage-request.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "games.script-storage-result",
++ "version": "1.0.0",
++ "owner": "games",
++ "schema": "games/script-storage-result.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "media.object.deleted",
"version": "1.0.0",
ddiff --git a/contracts/games/script-call-result.v1.json b/contracts/games/script-call-result.v1.json
nnew file mode 100644
iindex 00000000..6b1fa294
---- /dev/null
++++ b/contracts/games/script-call-result.v1.json
@@@ -0,0 +1,24 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-call-result.v1.json",
++ "title": "GamesScriptCallResult",
++ "description": "games.script-call-result@1: what a hook call produced: the number of intents it queued, or the error that made it fail (a mod that keeps throwing or overruns its budget is disabled).",
++ "type": "object",
++ "required": [
++ "ok"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "type": "boolean"
++ },
++ "intents": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "error": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++}
ddiff --git a/contracts/games/script-call.v1.json b/contracts/games/script-call.v1.json
nnew file mode 100644
iindex 00000000..0da90b41
---- /dev/null
++++ b/contracts/games/script-call.v1.json
@@@ -0,0 +1,18 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-call.v1.json",
++ "title": "GamesScriptCall",
++ "description": "games.script-call@1: one hook call into a script mod's QuickJS sandbox (games.script.run): the hook the place fires and its JSON payload. The call runs under the mod's CPU budget; changes come back only as intents the server validates.",
++ "type": "object",
++ "required": [
++ "hook"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "hook": {
++ "type": "string",
++ "pattern": "^[a-z][a-zA-Z0-9]{0,39}$"
++ },
++ "payload": {}
++ }
++}
ddiff --git a/contracts/games/script-intent.v1.json b/contracts/games/script-intent.v1.json
nnew file mode 100644
iindex 00000000..5a4996e9
---- /dev/null
++++ b/contracts/games/script-intent.v1.json
@@@ -0,0 +1,16 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-intent.v1.json",
++ "title": "GamesScriptIntent",
++ "description": "games.script-intent@1: game.emit(intent), a world intent a script queues (games.world.emit). The server validates it like any player's intent before applying it; an invalid one throws inside the script.",
++ "type": "object",
++ "required": [
++ "kind"
++ ],
++ "properties": {
++ "kind": {
++ "type": "string",
++ "pattern": "^[a-z][a-zA-Z0-9_.]{0,39}$"
++ }
++ }
++}
ddiff --git a/contracts/games/script-message.v1.json b/contracts/games/script-message.v1.json
nnew file mode 100644
iindex 00000000..6d182282
---- /dev/null
++++ b/contracts/games/script-message.v1.json
@@@ -0,0 +1,23 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-message.v1.json",
++ "title": "GamesScriptMessage",
++ "description": "games.script-message@1: game.message(playerId, text), a private announcement to one player in the mod's place, prefixed with the mod's name (games.player.message).",
++ "type": "object",
++ "required": [
++ "playerId",
++ "text"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "playerId": {
++ "type": "string",
++ "minLength": 1
++ },
++ "text": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 280
++ }
++ }
++}
ddiff --git a/contracts/games/script-players.v1.json b/contracts/games/script-players.v1.json
nnew file mode 100644
iindex 00000000..591bfb44
---- /dev/null
++++ b/contracts/games/script-players.v1.json
@@@ -0,0 +1,96 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-players.v1.json",
++ "title": "GamesScriptPlayers",
++ "description": "games.script-players@1: game.players() (every player in the mod's place) and game.player(id) (one, or null), read-only (games.players.read).",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "players"
++ ],
++ "properties": {
++ "players": {
++ "type": "array",
++ "items": {
++ "type": "object",
++ "required": [
++ "id",
++ "name"
++ ],
++ "properties": {
++ "id": {
++ "type": "string"
++ },
++ "name": {
++ "type": "string"
++ },
++ "pos": {
++ "type": "object",
++ "required": [
++ "x",
++ "y",
++ "z"
++ ],
++ "properties": {
++ "x": {
++ "type": "number"
++ },
++ "y": {
++ "type": "number"
++ },
++ "z": {
++ "type": "number"
++ }
++ }
++ },
++ "yaw": {
++ "type": "number"
++ }
++ }
++ }
++ }
++ }
++ },
++ {
++ "type": "object",
++ "required": [
++ "id",
++ "name"
++ ],
++ "properties": {
++ "id": {
++ "type": "string"
++ },
++ "name": {
++ "type": "string"
++ },
++ "pos": {
++ "type": "object",
++ "required": [
++ "x",
++ "y",
++ "z"
++ ],
++ "properties": {
++ "x": {
++ "type": "number"
++ },
++ "y": {
++ "type": "number"
++ },
++ "z": {
++ "type": "number"
++ }
++ }
++ },
++ "yaw": {
++ "type": "number"
++ }
++ }
++ },
++ {
++ "type": "null"
++ }
++ ]
++}
ddiff --git a/contracts/games/script-storage-request.v1.json b/contracts/games/script-storage-request.v1.json
nnew file mode 100644
iindex 00000000..70c1c251
---- /dev/null
++++ b/contracts/games/script-storage-request.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-storage-request.v1.json",
++ "title": "GamesScriptStorageRequest",
++ "description": "games.script-storage-request@1: game.storage.get(key), set(key, value), delete(key) and keys(prefix?) on the mod's key/value storage for its place (games.storage.kv): keys up to 128 bytes, values up to 8 KB of JSON, at most 1000 keys and 1 MB per mod per place.",
++ "type": "object",
++ "required": [
++ "op"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "op": {
++ "enum": [
++ "get",
++ "set",
++ "delete",
++ "keys"
++ ]
++ },
++ "key": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 128
++ },
++ "value": {},
++ "prefix": {
++ "type": "string",
++ "maxLength": 128
++ }
++ }
++}
ddiff --git a/contracts/games/script-storage-result.v1.json b/contracts/games/script-storage-result.v1.json
nnew file mode 100644
iindex 00000000..4ad4b957
---- /dev/null
++++ b/contracts/games/script-storage-result.v1.json
@@@ -0,0 +1,20 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-storage-result.v1.json",
++ "title": "GamesScriptStorageResult",
++ "description": "games.script-storage-result@1: a stored value (null when absent), the keys under a prefix, or an acknowledgement of a set or delete.",
++ "type": "object",
++ "additionalProperties": false,
++ "properties": {
++ "value": {},
++ "keys": {
++ "type": "array",
++ "items": {
++ "type": "string"
++ }
++ },
++ "ok": {
++ "type": "boolean"
++ }
++ }
++}
ddiff --git a/fixtures/games.script-call-result/invalid/negative.json b/fixtures/games.script-call-result/invalid/negative.json
nnew file mode 100644
iindex 00000000..8b4f0b9f
---- /dev/null
++++ b/fixtures/games.script-call-result/invalid/negative.json
@@@ -0,0 +1,4 @@
++{
++ "ok": true,
++ "intents": -1
++}
ddiff --git a/fixtures/games.script-call-result/invalid/no-ok.json b/fixtures/games.script-call-result/invalid/no-ok.json
nnew file mode 100644
iindex 00000000..345913d5
---- /dev/null
++++ b/fixtures/games.script-call-result/invalid/no-ok.json
@@@ -0,0 +1,3 @@
++{
++ "intents": 1
++}
ddiff --git a/fixtures/games.script-call-result/valid/failed.json b/fixtures/games.script-call-result/valid/failed.json
nnew file mode 100644
iindex 00000000..c933b72b
---- /dev/null
++++ b/fixtures/games.script-call-result/valid/failed.json
@@@ -0,0 +1,4 @@
++{
++ "ok": false,
++ "error": "budget: cpu 50 ms exceeded"
++}
ddiff --git a/fixtures/games.script-call-result/valid/ok.json b/fixtures/games.script-call-result/valid/ok.json
nnew file mode 100644
iindex 00000000..7c442ab3
---- /dev/null
++++ b/fixtures/games.script-call-result/valid/ok.json
@@@ -0,0 +1,4 @@
++{
++ "ok": true,
++ "intents": 2
++}
ddiff --git a/fixtures/games.script-call/invalid/bad-hook.json b/fixtures/games.script-call/invalid/bad-hook.json
nnew file mode 100644
iindex 00000000..d3385366
---- /dev/null
++++ b/fixtures/games.script-call/invalid/bad-hook.json
@@@ -0,0 +1,3 @@
++{
++ "hook": "../x"
++}
ddiff --git a/fixtures/games.script-call/invalid/no-hook.json b/fixtures/games.script-call/invalid/no-hook.json
nnew file mode 100644
iindex 00000000..d29bdbad
---- /dev/null
++++ b/fixtures/games.script-call/invalid/no-hook.json
@@@ -0,0 +1,3 @@
++{
++ "payload": {}
++}
ddiff --git a/fixtures/games.script-call/valid/join.json b/fixtures/games.script-call/valid/join.json
nnew file mode 100644
iindex 00000000..4e657e92
---- /dev/null
++++ b/fixtures/games.script-call/valid/join.json
@@@ -0,0 +1,6 @@
++{
++ "hook": "onPlayerJoin",
++ "payload": {
++ "playerId": "plr_1"
++ }
++}
ddiff --git a/fixtures/games.script-call/valid/tick.json b/fixtures/games.script-call/valid/tick.json
nnew file mode 100644
iindex 00000000..d0bc00a3
---- /dev/null
++++ b/fixtures/games.script-call/valid/tick.json
@@@ -0,0 +1,6 @@
++{
++ "hook": "onTick",
++ "payload": {
++ "dt": 0.05
++ }
++}
ddiff --git a/fixtures/games.script-intent/invalid/no-kind.json b/fixtures/games.script-intent/invalid/no-kind.json
nnew file mode 100644
iindex 00000000..17beca34
---- /dev/null
++++ b/fixtures/games.script-intent/invalid/no-kind.json
@@@ -0,0 +1,3 @@
++{
++ "item": "scrap"
++}
ddiff --git a/fixtures/games.script-intent/valid/spawn.json b/fixtures/games.script-intent/valid/spawn.json
nnew file mode 100644
iindex 00000000..ccd4a1f9
---- /dev/null
++++ b/fixtures/games.script-intent/valid/spawn.json
@@@ -0,0 +1,9 @@
++{
++ "kind": "spawnItem",
++ "item": "scrap",
++ "at": {
++ "x": 0,
++ "y": 0,
++ "z": 0
++ }
++}
ddiff --git a/fixtures/games.script-message/invalid/empty.json b/fixtures/games.script-message/invalid/empty.json
nnew file mode 100644
iindex 00000000..e66ffbde
---- /dev/null
++++ b/fixtures/games.script-message/invalid/empty.json
@@@ -0,0 +1,4 @@
++{
++ "playerId": "plr_1",
++ "text": ""
++}
ddiff --git a/fixtures/games.script-message/invalid/long.json b/fixtures/games.script-message/invalid/long.json
nnew file mode 100644
iindex 00000000..2457d453
---- /dev/null
++++ b/fixtures/games.script-message/invalid/long.json
@@@ -0,0 +1,4 @@
++{
++ "playerId": "plr_1",
++ "text": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
++}
ddiff --git a/fixtures/games.script-message/valid/hi.json b/fixtures/games.script-message/valid/hi.json
nnew file mode 100644
iindex 00000000..bb8cb448
---- /dev/null
++++ b/fixtures/games.script-message/valid/hi.json
@@@ -0,0 +1,4 @@
++{
++ "playerId": "plr_1",
++ "text": "Welcome to the scrapyard."
++}
ddiff --git a/fixtures/games.script-players/invalid/no-name.json b/fixtures/games.script-players/invalid/no-name.json
nnew file mode 100644
iindex 00000000..7b324769
---- /dev/null
++++ b/fixtures/games.script-players/invalid/no-name.json
@@@ -0,0 +1,7 @@
++{
++ "players": [
++ {
++ "id": "plr_1"
++ }
++ ]
++}
ddiff --git a/fixtures/games.script-players/valid/list.json b/fixtures/games.script-players/valid/list.json
nnew file mode 100644
iindex 00000000..200f1685
---- /dev/null
++++ b/fixtures/games.script-players/valid/list.json
@@@ -0,0 +1,14 @@
++{
++ "players": [
++ {
++ "id": "plr_1",
++ "name": "scrapper",
++ "pos": {
++ "x": 1,
++ "y": 0,
++ "z": 2
++ },
++ "yaw": 1.5
++ }
++ ]
++}
ddiff --git a/fixtures/games.script-players/valid/none.json b/fixtures/games.script-players/valid/none.json
nnew file mode 100644
iindex 00000000..19765bd5
---- /dev/null
++++ b/fixtures/games.script-players/valid/none.json
@@@ -0,0 +1 @@
++null
ddiff --git a/fixtures/games.script-storage-request/invalid/bad-op.json b/fixtures/games.script-storage-request/invalid/bad-op.json
nnew file mode 100644
iindex 00000000..417bf922
---- /dev/null
++++ b/fixtures/games.script-storage-request/invalid/bad-op.json
@@@ -0,0 +1,3 @@
++{
++ "op": "drop"
++}
ddiff --git a/fixtures/games.script-storage-request/invalid/long-key.json b/fixtures/games.script-storage-request/invalid/long-key.json
nnew file mode 100644
iindex 00000000..3a29660d
---- /dev/null
++++ b/fixtures/games.script-storage-request/invalid/long-key.json
@@@ -0,0 +1,4 @@
++{
++ "op": "get",
++ "key": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
++}
ddiff --git a/fixtures/games.script-storage-request/valid/keys.json b/fixtures/games.script-storage-request/valid/keys.json
nnew file mode 100644
iindex 00000000..d26b0dce
---- /dev/null
++++ b/fixtures/games.script-storage-request/valid/keys.json
@@@ -0,0 +1,4 @@
++{
++ "op": "keys",
++ "prefix": "score:"
++}
ddiff --git a/fixtures/games.script-storage-request/valid/set.json b/fixtures/games.script-storage-request/valid/set.json
nnew file mode 100644
iindex 00000000..ae66ef32
---- /dev/null
++++ b/fixtures/games.script-storage-request/valid/set.json
@@@ -0,0 +1,5 @@
++{
++ "op": "set",
++ "key": "visits",
++ "value": 3
++}
ddiff --git a/fixtures/games.script-storage-result/invalid/extra.json b/fixtures/games.script-storage-result/invalid/extra.json
nnew file mode 100644
iindex 00000000..c9c4fe01
---- /dev/null
++++ b/fixtures/games.script-storage-result/invalid/extra.json
@@@ -0,0 +1,4 @@
++{
++ "value": 1,
++ "other": true
++}
ddiff --git a/fixtures/games.script-storage-result/valid/keys.json b/fixtures/games.script-storage-result/valid/keys.json
nnew file mode 100644
iindex 00000000..2cd360be
---- /dev/null
++++ b/fixtures/games.script-storage-result/valid/keys.json
@@@ -0,0 +1,6 @@
++{
++ "keys": [
++ "score:a",
++ "score:b"
++ ]
++}
ddiff --git a/fixtures/games.script-storage-result/valid/value.json b/fixtures/games.script-storage-result/valid/value.json
nnew file mode 100644
iindex 00000000..d95c5ae1
---- /dev/null
++++ b/fixtures/games.script-storage-result/valid/value.json
@@@ -0,0 +1,3 @@
++{
++ "value": 3
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex 597f4b90..486537a3 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -49243,6 +49243,269 @@
}
}
},
++ "games.script-call": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-call.v1.json",
++ "title": "GamesScriptCall",
++ "description": "games.script-call@1: one hook call into a script mod's QuickJS sandbox (games.script.run): the hook the place fires and its JSON payload. The call runs under the mod's CPU budget; changes come back only as intents the server validates.",
++ "type": "object",
++ "required": [
++ "hook"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "hook": {
++ "type": "string",
++ "pattern": "^[a-z][a-zA-Z0-9]{0,39}$"
++ },
++ "payload": {}
++ }
++ }
++ },
++ "games.script-call-result": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-call-result.v1.json",
++ "title": "GamesScriptCallResult",
++ "description": "games.script-call-result@1: what a hook call produced: the number of intents it queued, or the error that made it fail (a mod that keeps throwing or overruns its budget is disabled).",
++ "type": "object",
++ "required": [
++ "ok"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "type": "boolean"
++ },
++ "intents": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "error": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++ }
++ },
++ "games.script-players": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-players.v1.json",
++ "title": "GamesScriptPlayers",
++ "description": "games.script-players@1: game.players() (every player in the mod's place) and game.player(id) (one, or null), read-only (games.players.read).",
++ "anyOf": [
++ {
++ "type": "object",
++ "required": [
++ "players"
++ ],
++ "properties": {
++ "players": {
++ "type": "array",
++ "items": {
++ "type": "object",
++ "required": [
++ "id",
++ "name"
++ ],
++ "properties": {
++ "id": {
++ "type": "string"
++ },
++ "name": {
++ "type": "string"
++ },
++ "pos": {
++ "type": "object",
++ "required": [
++ "x",
++ "y",
++ "z"
++ ],
++ "properties": {
++ "x": {
++ "type": "number"
++ },
++ "y": {
++ "type": "number"
++ },
++ "z": {
++ "type": "number"
++ }
++ }
++ },
++ "yaw": {
++ "type": "number"
++ }
++ }
++ }
++ }
++ }
++ },
++ {
++ "type": "object",
++ "required": [
++ "id",
++ "name"
++ ],
++ "properties": {
++ "id": {
++ "type": "string"
++ },
++ "name": {
++ "type": "string"
++ },
++ "pos": {
++ "type": "object",
++ "required": [
++ "x",
++ "y",
++ "z"
++ ],
++ "properties": {
++ "x": {
++ "type": "number"
++ },
++ "y": {
++ "type": "number"
++ },
++ "z": {
++ "type": "number"
++ }
++ }
++ },
++ "yaw": {
++ "type": "number"
++ }
++ }
++ },
++ {
++ "type": "null"
++ }
++ ]
++ }
++ },
++ "games.script-message": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-message.v1.json",
++ "title": "GamesScriptMessage",
++ "description": "games.script-message@1: game.message(playerId, text), a private announcement to one player in the mod's place, prefixed with the mod's name (games.player.message).",
++ "type": "object",
++ "required": [
++ "playerId",
++ "text"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "playerId": {
++ "type": "string",
++ "minLength": 1
++ },
++ "text": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 280
++ }
++ }
++ }
++ },
++ "games.script-intent": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-intent.v1.json",
++ "title": "GamesScriptIntent",
++ "description": "games.script-intent@1: game.emit(intent), a world intent a script queues (games.world.emit). The server validates it like any player's intent before applying it; an invalid one throws inside the script.",
++ "type": "object",
++ "required": [
++ "kind"
++ ],
++ "properties": {
++ "kind": {
++ "type": "string",
++ "pattern": "^[a-z][a-zA-Z0-9_.]{0,39}$"
++ }
++ }
++ }
++ },
++ "games.script-storage-request": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-storage-request.v1.json",
++ "title": "GamesScriptStorageRequest",
++ "description": "games.script-storage-request@1: game.storage.get(key), set(key, value), delete(key) and keys(prefix?) on the mod's key/value storage for its place (games.storage.kv): keys up to 128 bytes, values up to 8 KB of JSON, at most 1000 keys and 1 MB per mod per place.",
++ "type": "object",
++ "required": [
++ "op"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "op": {
++ "enum": [
++ "get",
++ "set",
++ "delete",
++ "keys"
++ ]
++ },
++ "key": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 128
++ },
++ "value": {},
++ "prefix": {
++ "type": "string",
++ "maxLength": 128
++ }
++ }
++ }
++ },
++ "games.script-storage-result": {
++ "version": "1.0.0",
++ "owner": "games",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/games/script-storage-result.v1.json",
++ "title": "GamesScriptStorageResult",
++ "description": "games.script-storage-result@1: a stored value (null when absent), the keys under a prefix, or an acknowledgement of a set or delete.",
++ "type": "object",
++ "additionalProperties": false,
++ "properties": {
++ "value": {},
++ "keys": {
++ "type": "array",
++ "items": {
++ "type": "string"
++ }
++ },
++ "ok": {
++ "type": "boolean"
++ }
++ }
++ }
++ },
"media.object.deleted": {
"version": "1.0.0",
"owner": "media",
ddiff --git a/generated/openapi/actor.json b/generated/openapi/actor.json
iindex cedb5744..1241e2f1 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.141.0",
-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 cb9b979c..9ce5e82f 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.141.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 c4dc19b2..e09c8584 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.141.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 082af1d3..60dc19d1 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.141.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 cabc1e4e..4d20322f 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.141.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 a1519518..c3311ebc 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.141.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 adb30643..a2c48f52 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.141.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 b5f53fd3..550cfc37 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.141.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 12f7ba07..af13b336 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.141.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 07173c48..4790a731 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.141.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 66bb2c16..c1516e95 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.141.0",
-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 6cb88df7..db95a0f4 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.141.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
@@@ -16,6 +16,128 @@
}
],
"paths": {
++ "/api/mods": {
++ "post": {
++ "operationId": "post_api_mods",
++ "summary": "Run a staff-installed script mod (games-quickjs@1, one or more module files in its content pack, imports resolved inside the pack only) in its own QuickJS sandbox per place, under the pack's CPU and m",
++ "description": "**games.script.run** (public): Run a staff-installed script mod (games-quickjs@1, one or more module files in its content pack, imports resolved inside the pack only) in its own QuickJS sandbox per place, under the pack's CPU and memory budgets; a staff hot reload replaces the code and keeps its storage, and a reload that fails to start keeps the previous version running. The script sees only the bindings its install was granted.\n\nRoute note: install, staff",
++ "tags": [
++ "games.script"
++ ],
++ "x-openvibe-capabilities": [
++ "games.script.run"
++ ],
++ "x-openvibe-visibility": [
++ "public"
++ ],
++ "x-openvibe-quota-class": "games-mod-runtime",
++ "security": [
++ {
++ "openvibeToken": [
++ "games.script.run"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/games.script-call.v1"
++ }
++ }
++ }
++ },
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/games.script-call-result.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/api/mods/{id}/reload": {
++ "post": {
++ "operationId": "post_api_mods_id_reload",
++ "summary": "Run a staff-installed script mod (games-quickjs@1, one or more module files in its content pack, imports resolved inside the pack only) in its own QuickJS sandbox per place, under the pack's CPU and m",
++ "description": "**games.script.run** (public): Run a staff-installed script mod (games-quickjs@1, one or more module files in its content pack, imports resolved inside the pack only) in its own QuickJS sandbox per place, under the pack's CPU and memory budgets; a staff hot reload replaces the code and keeps its storage, and a reload that fails to start keeps the previous version running. The script sees only the bindings its install was granted.\n\nRoute note: staff",
++ "tags": [
++ "games.script"
++ ],
++ "x-openvibe-capabilities": [
++ "games.script.run"
++ ],
++ "x-openvibe-visibility": [
++ "public"
++ ],
++ "x-openvibe-quota-class": "games-mod-runtime",
++ "security": [
++ {
++ "openvibeToken": [
++ "games.script.run"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/games.script-call.v1"
++ }
++ }
++ }
++ },
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/games.script-call-result.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
"/api/v1/mods": {
"get": {
"operationId": "get_api_v1_mods",
@@@ -64,7 +186,7 @@
"post": {
"operationId": "post_api_v1_mods",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -176,7 +298,7 @@
"get": {
"operationId": "get_api_v1_mods_id_audit",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -235,7 +357,7 @@
"post": {
"operationId": "post_api_v1_mods_id_disable",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -301,7 +423,7 @@
"post": {
"operationId": "post_api_v1_mods_id_enable",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -367,7 +489,7 @@
"post": {
"operationId": "post_api_v1_mods_id_grants",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -433,7 +555,7 @@
"delete": {
"operationId": "delete_api_v1_mods_id_grants_capability",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -496,11 +618,77 @@
}
}
},
++ "/api/v1/mods/{id}/reload": {
++ "post": {
++ "operationId": "post_api_v1_mods_id_reload",
++ "summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
++ "tags": [
++ "games.mod"
++ ],
++ "x-openvibe-capabilities": [
++ "games.mod.manage"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "games-admin",
++ "security": [
++ {
++ "openvibeToken": [
++ "games.mod.manage"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/games.mod-manage-request.v1"
++ }
++ }
++ }
++ },
++ "parameters": [
++ {
++ "name": "id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/games.mod-manage-result.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
"/api/v1/mods/{id}/revoke": {
"post": {
"operationId": "post_api_v1_mods_id_revoke",
"summary": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, di",
-- "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "**games.mod.manage** (first-party): Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"tags": [
"games.mod"
],
@@@ -937,6 +1125,44 @@
}
}
},
++ "games.script-call-result.v1": {
++ "title": "GamesScriptCallResult",
++ "description": "games.script-call-result@1: what a hook call produced: the number of intents it queued, or the error that made it fail (a mod that keeps throwing or overruns its budget is disabled).",
++ "type": "object",
++ "required": [
++ "ok"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "type": "boolean"
++ },
++ "intents": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "error": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++ },
++ "games.script-call.v1": {
++ "title": "GamesScriptCall",
++ "description": "games.script-call@1: one hook call into a script mod's QuickJS sandbox (games.script.run): the hook the place fires and its JSON payload. The call runs under the mod's CPU budget; changes come back only as intents the server validates.",
++ "type": "object",
++ "required": [
++ "hook"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "hook": {
++ "type": "string",
++ "pattern": "^[a-z][a-zA-Z0-9]{0,39}$"
++ },
++ "payload": {}
++ }
++ },
"identity.subject-ref.v1": {
"title": "SubjectRef",
"description": "The one cross-platform reference to an actor. Issued by OpenVibe.Network. Never a service-local integer id.",
@@@ -1378,13 +1604,33 @@
}
},
"x-openvibe-other-bindings": [
++ {
++ "capability": "games.player.message",
++ "binding": "mod runtime binding game.message (apps/server/src/mods/script/host.ts)"
++ },
++ {
++ "capability": "games.players.read",
++ "binding": "mod runtime binding game.players / game.player (apps/server/src/mods/script/host.ts)"
++ },
{
"capability": "games.prop.place",
"binding": "mod runtime binding ModApi.placeProp / ModApi.removeProp (apps/server/src/mods/runtime.ts)"
},
++ {
++ "capability": "games.script.run",
++ "binding": "mod runtime: games-quickjs@1 sandbox (apps/server/src/mods/script/host.ts, quickjs.ts)"
++ },
++ {
++ "capability": "games.storage.kv",
++ "binding": "mod runtime binding game.storage (apps/server/src/mods/script/host.ts, storage.ts)"
++ },
{
"capability": "games.world.announce",
"binding": "mod runtime binding ModApi.announce (apps/server/src/mods/runtime.ts)"
++ },
++ {
++ "capability": "games.world.emit",
++ "binding": "mod runtime binding game.emit (apps/server/src/mods/script/host.ts)"
}
]
}
ddiff --git a/generated/openapi/host.json b/generated/openapi/host.json
iindex e2ff230a..01515655 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.141.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 985713dd..3871d300 100644
---- a/generated/openapi/index.json
++++ b/generated/openapi/index.json
@@@ -82,8 +82,8 @@
"service": "games",
"name": "OpenVibe.Games",
"origin": "https://openvibe.games",
-- "operations": 9,
-- "capabilities": 4
++ "operations": 12,
++ "capabilities": 9
},
{
"service": "host",
ddiff --git a/generated/openapi/inventory.json b/generated/openapi/inventory.json
iindex 51478796..1e93367d 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.141.0",
-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 536896c8..cfe0b602 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.141.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 f69a4d81..4582a205 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.141.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 74a6956d..f217295b 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.141.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 eb50112f..f0cbacd8 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.141.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 0638420e..39753af3 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.141.0",
-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 1d8f1242..f9d04439 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.141.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 1a78eecd..23d4d39d 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.141.0",
-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 71cedbc4..06c53642 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.141.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 04551d8d..154113b9 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.141.0",
-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 0a190eb2..92090819 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.141.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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/tips.json b/generated/openapi/tips.json
iindex ed23dea8..77b5ff22 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.141.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 1ee6a51d..8522acc7 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.141.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 b4a2d115..41f03ce2 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.141.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 71e73180..48c33043 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.141.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 8ee32608..763cd86f 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.141.0",
-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 71d4a4bf..8ac268ab 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.141.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.141.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.142.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.142.0): each operation lists the capabilities it performs; a token for the 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 5390cb62..27506f25 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -50126,6 +50126,92 @@ export interface GamesModView {
updated_at: string;
}
++/** [email protected] (owner: games) */
++/**
++ * games.script-call@1: one hook call into a script mod's QuickJS sandbox (games.script.run): the hook the place fires and its JSON payload. The call runs under the mod's CPU budget; changes come back only as intents the server validates.
++ */
++export interface GamesScriptCall {
++ hook: string;
++ payload?: unknown;
++}
++
++/** [email protected] (owner: games) */
++/**
++ * games.script-call-result@1: what a hook call produced: the number of intents it queued, or the error that made it fail (a mod that keeps throwing or overruns its budget is disabled).
++ */
++export interface GamesScriptCallResult {
++ ok: boolean;
++ intents?: number;
++ error?: string;
++}
++
++/** [email protected] (owner: games) */
++/**
++ * games.script-players@1: game.players() (every player in the mod's place) and game.player(id) (one, or null), read-only (games.players.read).
++ */
++export type GamesScriptPlayers =
++ | {
++ players: {
++ id: string;
++ name: string;
++ pos?: {
++ x: number;
++ y: number;
++ z: number;
++ };
++ yaw?: number;
++ }[];
++ }
++ | {
++ id: string;
++ name: string;
++ pos?: {
++ x: number;
++ y: number;
++ z: number;
++ };
++ yaw?: number;
++ }
++ | null;
++
++/** [email protected] (owner: games) */
++/**
++ * games.script-message@1: game.message(playerId, text), a private announcement to one player in the mod's place, prefixed with the mod's name (games.player.message).
++ */
++export interface GamesScriptMessage {
++ playerId: string;
++ text: string;
++}
++
++/** [email protected] (owner: games) */
++/**
++ * games.script-intent@1: game.emit(intent), a world intent a script queues (games.world.emit). The server validates it like any player's intent before applying it; an invalid one throws inside the script.
++ */
++export interface GamesScriptIntent {
++ kind: string;
++}
++
++/** [email protected] (owner: games) */
++/**
++ * games.script-storage-request@1: game.storage.get(key), set(key, value), delete(key) and keys(prefix?) on the mod's key/value storage for its place (games.storage.kv): keys up to 128 bytes, values up to 8 KB of JSON, at most 1000 keys and 1 MB per mod per place.
++ */
++export interface GamesScriptStorageRequest {
++ op: "get" | "set" | "delete" | "keys";
++ key?: string;
++ value?: unknown;
++ prefix?: string;
++}
++
++/** [email protected] (owner: games) */
++/**
++ * games.script-storage-result@1: a stored value (null when absent), the keys under a prefix, or an acknowledgement of a set or delete.
++ */
++export interface GamesScriptStorageResult {
++ value?: unknown;
++ keys?: string[];
++ ok?: boolean;
++}
++
/** [email protected] (owner: media) */
/**
* media.object.deleted v1 (OpenVibe.Media server/events.js objectChangeEvent and recordObjectChanges, commit 039dc48, from the media_object_changes rows that the AFTER UPDATE OF lifecycle_status trigger on media_objects writes). An object's lifecycle_status became deleted: a native object soft-deleted through DELETE /api/v2/:app/objects/:id, or an inherited vods/clips/files/pastes row removed, which marks its object deleted. Every write path counts (operator SQL included), and the event exists if and only if the change committed: the trigger row and the outbox envelope are written in the transaction of the change, or by the relay's drain for a change made outside Media's own transactions. Consumers drop any public copy, index entry or cache they hold for the object (roadmap §29.3). Deliberately minimal, identity and state only: never the title, description or metadata, the owner's ids or subject, storage keys, paths or providers, sizes or hashes. Developer-project sandbox tenants produce none. Envelope: subject { type: object, id: <object_id> }, visibility internal, priority important, actor service:media.
ddiff --git a/manifests/capabilities/games.mod.manage.json b/manifests/capabilities/games.mod.manage.json
iindex b95a91ea..a679d1db 100644
---- a/manifests/capabilities/games.mod.manage.json
++++ b/manifests/capabilities/games.mod.manage.json
@@@ -4,10 +4,14 @@
"owner": "games",
"status": "active",
"visibility": "first-party",
-- "description": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session.",
++ "description": "Manage mod installs in the browser game's registry (ADR-013): install a mods/mod-manifest.v1 manifest with its games-content@1 pack, approve or revoke individual capabilities of an install, enable, disable, and revoke an install for good (its effects end on the next server tick). Every action is audited and published as a games.mod.* event. Trust tiers are metadata and never grant anything. Also accepted from an openvibe.network owner/admin session. Reload replaces a running script mod's code (games-quickjs@1) and keeps its storage; a reload that fails to start keeps the previous version.",
"inputSchema": "games.mod-manage-request@1",
-- "permissions": ["games:mods:admin"],
-- "resourceConstraints": ["none"],
++ "permissions": [
++ "games:mods:admin"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
"quotaClass": "games-admin",
"events": [
"games.mod.installed",
@@@ -20,6 +24,7 @@
"POST /api/v1/mods",
"POST /api/v1/mods/:id/enable",
"POST /api/v1/mods/:id/disable",
++ "POST /api/v1/mods/:id/reload",
"POST /api/v1/mods/:id/revoke",
"POST /api/v1/mods/:id/grants",
"DELETE /api/v1/mods/:id/grants/:capability",
ddiff --git a/manifests/capabilities/games.player.message.json b/manifests/capabilities/games.player.message.json
nnew file mode 100644
iindex 00000000..3cd81109
---- /dev/null
++++ b/manifests/capabilities/games.player.message.json
@@@ -0,0 +1,21 @@
++{
++ "id": "games.player.message",
++ "version": "1.0",
++ "owner": "games",
++ "status": "active",
++ "visibility": "public",
++ "description": "Script binding for mods (games-quickjs@1): game.message, a validated private announcement to one player in the mod's current place, prefixed with the mod's name. Absent unless granted.",
++ "permissions": [
++ "games:player:message"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "games-mod-runtime",
++ "events": [],
++ "implementedBy": [
++ "mod runtime binding game.message (apps/server/src/mods/script/host.ts)"
++ ],
++ "inputSchema": "games.script-message@1",
++ "outputSchema": "common.no-body@1"
++}
ddiff --git a/manifests/capabilities/games.players.read.json b/manifests/capabilities/games.players.read.json
nnew file mode 100644
iindex 00000000..5b3bb16f
---- /dev/null
++++ b/manifests/capabilities/games.players.read.json
@@@ -0,0 +1,21 @@
++{
++ "id": "games.players.read",
++ "version": "1.0",
++ "owner": "games",
++ "status": "active",
++ "visibility": "public",
++ "description": "Script binding for mods (games-quickjs@1): game.players and game.player, read-only views of the players in the mod's current place. Absent from the script's game object unless the install was granted it; checked against the install's approved capabilities, which travel in the def-set digest.",
++ "permissions": [
++ "games:players:read"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "games-mod-runtime",
++ "events": [],
++ "implementedBy": [
++ "mod runtime binding game.players / game.player (apps/server/src/mods/script/host.ts)"
++ ],
++ "inputSchema": "common.no-body@1",
++ "outputSchema": "games.script-players@1"
++}
ddiff --git a/manifests/capabilities/games.script.run.json b/manifests/capabilities/games.script.run.json
nnew file mode 100644
iindex 00000000..fb8c203c
---- /dev/null
++++ b/manifests/capabilities/games.script.run.json
@@@ -0,0 +1,23 @@
++{
++ "id": "games.script.run",
++ "version": "1.0",
++ "owner": "games",
++ "status": "active",
++ "visibility": "public",
++ "description": "Run a staff-installed script mod (games-quickjs@1, one or more module files in its content pack, imports resolved inside the pack only) in its own QuickJS sandbox per place, under the pack's CPU and memory budgets; a staff hot reload replaces the code and keeps its storage, and a reload that fails to start keeps the previous version running. The script sees only the bindings its install was granted.",
++ "permissions": [
++ "games:script:run"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "games-mod-runtime",
++ "events": [],
++ "implementedBy": [
++ "mod runtime: games-quickjs@1 sandbox (apps/server/src/mods/script/host.ts, quickjs.ts)",
++ "POST /api/mods (install, staff)",
++ "POST /api/mods/:id/reload (staff)"
++ ],
++ "inputSchema": "games.script-call@1",
++ "outputSchema": "games.script-call-result@1"
++}
ddiff --git a/manifests/capabilities/games.storage.kv.json b/manifests/capabilities/games.storage.kv.json
nnew file mode 100644
iindex 00000000..122c6ee5
---- /dev/null
++++ b/manifests/capabilities/games.storage.kv.json
@@@ -0,0 +1,21 @@
++{
++ "id": "games.storage.kv",
++ "version": "1.0",
++ "owner": "games",
++ "status": "active",
++ "visibility": "public",
++ "description": "Script binding for mods (games-quickjs@1): game.storage get/set/delete/keys, key/value storage per mod per place on the Games database: keys up to 128 bytes, values up to 8 KB of JSON, at most 1000 keys and 1 MB per mod per place, writes counted against the mod's CPU budget; a refusal is an error inside the mod. Absent unless granted.",
++ "permissions": [
++ "games:storage:kv"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "games-mod-runtime",
++ "events": [],
++ "implementedBy": [
++ "mod runtime binding game.storage (apps/server/src/mods/script/host.ts, storage.ts)"
++ ],
++ "inputSchema": "games.script-storage-request@1",
++ "outputSchema": "games.script-storage-result@1"
++}
ddiff --git a/manifests/capabilities/games.world.emit.json b/manifests/capabilities/games.world.emit.json
nnew file mode 100644
iindex 00000000..f082638d
---- /dev/null
++++ b/manifests/capabilities/games.world.emit.json
@@@ -0,0 +1,21 @@
++{
++ "id": "games.world.emit",
++ "version": "1.0",
++ "owner": "games",
++ "status": "active",
++ "visibility": "public",
++ "description": "Script binding for mods (games-quickjs@1): game.emit, which queues world intents that the server validates like any player intent before applying them; a mod never mutates state directly. Absent unless granted.",
++ "permissions": [
++ "games:world:emit"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "games-mod-runtime",
++ "events": [],
++ "implementedBy": [
++ "mod runtime binding game.emit (apps/server/src/mods/script/host.ts)"
++ ],
++ "inputSchema": "games.script-intent@1",
++ "outputSchema": "common.no-body@1"
++}
ddiff --git a/manifests/services/games.json b/manifests/services/games.json
iindex ba351a5f..eee2f53b 100644
---- a/manifests/services/games.json
++++ b/manifests/services/games.json
@@@ -31,7 +31,12 @@
"games.mod.manage",
"games.mod.read",
"games.world.announce",
-- "games.prop.place"
++ "games.prop.place",
++ "games.script.run",
++ "games.players.read",
++ "games.player.message",
++ "games.world.emit",
++ "games.storage.kv"
],
"eventsProduced": [
"games.player.joined",
ddiff --git a/package.json b/package.json
iindex 1a978ceb..5c3d3d1d 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.141.0",
++ "version": "0.142.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",