openvibers/openvibe.contracts Commits

v0.72.0: mod principals in Network (roadmap WS-M task 3, ADR-013). mods.grant.manage is active: the owning runtime registers an install's principal mod:<mod_id> (POST /internal/mods, network.mod-install-request@1: the manifest and the subset approved at install, the rest pending), approves or revokes one capability (POST /internal/mods/{id}/grants, network.mod-grant-change@1), revokes the install (POST /internal/mods/{id}/revoke) and reads them (GET /internal/mods[/{id}]). Only the owner or Network staff (staff.games.manage) change a mod. Adds network.mod-principal@1 and the event network.mod.grants_changed@1 (the complete approved set by revision, the change, runtime or staff), which Games consumes.

OP OpenVibers committed 27 Sept 2026 · 8cccacdefa · 45 files, +1241 −61


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 3523af48..ad314064 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -6,6 +6,13 @@ the notes were in the tag and commit messages (`git tag -n1`).
## Unreleased
++## 0.72.0 — 2026-09-27
++
++**Mod principals in Network** (roadmap WS-M task 3, ADR-013).
++- `mods.grant.manage` is active. A runtime (OpenVibe.Games) registers an install's principal `mod:<mod_id>` (`POST /internal/mods`, `network.mod-install-request@1`: the manifest, and the subset staff approved at install; the rest stays pending). It then approves or revokes one capability (`POST /internal/mods/{mod_id}/grants`, `network.mod-grant-change@1`) or revokes the install (`POST /internal/mods/{mod_id}/revoke`). It reads them with `GET /internal/mods[/{mod_id}]`. Only the owning runtime or Network staff (`staff.games.manage`) change a mod.
++- `network.mod-principal@1`: the principal with requested, approved, pending and revoked capabilities, and a revision.
++- `network.mod.grants_changed@1` (internal): after every change, the complete approved set (by revision), the change, and whether the runtime or staff made it. The owning runtime sets its copy to it. Games lists it as consumed.
++
## 0.71.0 — 2026-09-27
**Account export and deletion** (roadmap WS-B task 7, ADR-033).
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex 7ba9ffd2..14082392 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -2476,6 +2476,46 @@
"status": "active",
"adr": "ADR-033"
},
++ {
++ "id": "network.mod.grants_changed",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "events/payloads/network.mod.grants_changed.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active",
++ "adr": "ADR-013"
++ },
++ {
++ "id": "network.mod-install-request",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "network/mod-install-request.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active",
++ "adr": "ADR-013"
++ },
++ {
++ "id": "network.mod-grant-change",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "network/mod-grant-change.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active",
++ "adr": "ADR-013"
++ },
++ {
++ "id": "network.mod-principal",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "network/mod-principal.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active",
++ "adr": "ADR-013"
++ },
{
"id": "network.subject.merged",
"version": "1.0.0",
ddiff --git a/contracts/events/payloads/network.mod.grants_changed.v1.json b/contracts/events/payloads/network.mod.grants_changed.v1.json
nnew file mode 100644
iindex 00000000..7873f21f
---- /dev/null
++++ b/contracts/events/payloads/network.mod.grants_changed.v1.json
@@@ -0,0 +1,86 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/network.mod.grants_changed.v1.json",
++ "title": "NetworkModGrantsChangedPayload",
++ "description": "network.mod.grants_changed v1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod principal's grants changed: registered, a capability approved or revoked, or the whole install revoked. `approved` is the complete approved set after the change, so the owning runtime sets its copy to it (idempotent by revision: an older revision changes nothing). `by` says whether the owning runtime or Network staff made the change; a runtime applies both.",
++ "type": "object",
++ "required": [
++ "mod_id",
++ "owner",
++ "status",
++ "approved",
++ "revision",
++ "change",
++ "by"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "mod_id": {
++ "type": "string",
++ "pattern": "^mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "owner": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,31}$"
++ },
++ "status": {
++ "enum": [
++ "active",
++ "revoked"
++ ]
++ },
++ "approved": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "pending": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1
++ },
++ "change": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "action"
++ ],
++ "properties": {
++ "action": {
++ "enum": [
++ "register",
++ "approve",
++ "revoke",
++ "revoke_all"
++ ]
++ },
++ "capability": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ }
++ },
++ "by": {
++ "enum": [
++ "runtime",
++ "staff"
++ ]
++ },
++ "reason": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++}
ddiff --git a/contracts/network/mod-grant-change.v1.json b/contracts/network/mod-grant-change.v1.json
nnew file mode 100644
iindex 00000000..3ccbb2c0
---- /dev/null
++++ b/contracts/network/mod-grant-change.v1.json
@@@ -0,0 +1,32 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/mod-grant-change.v1.json",
++ "title": "NetworkModGrantChange",
++ "description": "network.mod-grant-change@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): approve or revoke one requested capability of a mod principal, POST /internal/mods/{mod_id}/grants (the owning runtime, mods.grant.manage) or POST /api/admin/mods/{mod_id}/grants (staff.games.manage, with a reason).",
++ "type": "object",
++ "required": [
++ "capability",
++ "action"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "capability": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "action": {
++ "enum": [
++ "approve",
++ "revoke"
++ ]
++ },
++ "actor": {
++ "type": "string",
++ "maxLength": 80
++ },
++ "reason": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++}
ddiff --git a/contracts/network/mod-install-request.v1.json b/contracts/network/mod-install-request.v1.json
nnew file mode 100644
iindex 00000000..f06fbfe7
---- /dev/null
++++ b/contracts/network/mod-install-request.v1.json
@@@ -0,0 +1,32 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/mod-install-request.v1.json",
++ "title": "NetworkModInstallRequest",
++ "description": "network.mod-install-request@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a runtime (OpenVibe.Games) registers an install's mod principal, POST /internal/mods with capability mods.grant.manage. The manifest (mods.mod-manifest@1) names the requested capabilities; `approve` is the subset staff approved at install, and the rest stays pending. The runtime that registers a mod is its owner: only it (or Network staff) changes its grants. Registering the same mod again answers the existing principal.",
++ "type": "object",
++ "required": [
++ "manifest"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "manifest": {
++ "type": "object",
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ "approve": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ "actor": {
++ "type": "string",
++ "maxLength": 80,
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ }
++ }
++}
ddiff --git a/contracts/network/mod-principal.v1.json b/contracts/network/mod-principal.v1.json
nnew file mode 100644
iindex 00000000..5388c2ed
---- /dev/null
++++ b/contracts/network/mod-principal.v1.json
@@@ -0,0 +1,99 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/mod-principal.v1.json",
++ "title": "NetworkModPrincipal",
++ "description": "network.mod-principal@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod install's principal, `mod:<mod_id>`. Its grants are the approved subset of the capabilities its manifest requests; the rest are pending (never approved) or revoked. A revoked principal (the install ended) has no approved grants and never gets any again. The owning runtime keeps a copy of `approved` for its hot path and follows network.mod.grants_changed.",
++ "type": "object",
++ "required": [
++ "principal",
++ "mod_id",
++ "owner",
++ "runtime",
++ "status",
++ "requested",
++ "approved",
++ "pending",
++ "revoked",
++ "revision",
++ "updated_at"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "principal": {
++ "type": "string",
++ "pattern": "^mod:mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "mod_id": {
++ "type": "string",
++ "pattern": "^mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "owner": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,31}$",
++ "description": "The runtime service that registered it (games)."
++ },
++ "runtime": {
++ "type": "string",
++ "maxLength": 60,
++ "description": "The manifest's runtime, e.g. games-content@1."
++ },
++ "name": {
++ "type": "string",
++ "maxLength": 120
++ },
++ "version": {
++ "type": "string",
++ "maxLength": 40
++ },
++ "status": {
++ "enum": [
++ "active",
++ "revoked"
++ ]
++ },
++ "requested": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "approved": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "pending": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revoked": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1
++ },
++ "updated_at": {
++ "type": "string",
++ "format": "date-time"
++ }
++ }
++}
ddiff --git a/fixtures/network.mod-grant-change/invalid/grant-all.json b/fixtures/network.mod-grant-change/invalid/grant-all.json
nnew file mode 100644
iindex 00000000..9f2e6e5f
---- /dev/null
++++ b/fixtures/network.mod-grant-change/invalid/grant-all.json
@@@ -0,0 +1 @@
++{"capability":"*","action":"approve"}
ddiff --git a/fixtures/network.mod-grant-change/valid/approve.json b/fixtures/network.mod-grant-change/valid/approve.json
nnew file mode 100644
iindex 00000000..0b76681a
---- /dev/null
++++ b/fixtures/network.mod-grant-change/valid/approve.json
@@@ -0,0 +1 @@
++{"capability":"games.world.announce","action":"approve"}
ddiff --git a/fixtures/network.mod-install-request/invalid/no-manifest.json b/fixtures/network.mod-install-request/invalid/no-manifest.json
nnew file mode 100644
iindex 00000000..1927e814
---- /dev/null
++++ b/fixtures/network.mod-install-request/invalid/no-manifest.json
@@@ -0,0 +1 @@
++{"approve":[]}
ddiff --git a/fixtures/network.mod-install-request/valid/install.json b/fixtures/network.mod-install-request/valid/install.json
nnew file mode 100644
iindex 00000000..b60b4d3b
---- /dev/null
++++ b/fixtures/network.mod-install-request/valid/install.json
@@@ -0,0 +1 @@
++{"manifest":{"id":"mod_01JAB2C3D4E5F6G7H8J9K0MNPQ"},"approve":["games.world.announce"],"actor":"usr_01JAB2C3D4E5F6G7H8J9K0MNPR"}
ddiff --git a/fixtures/network.mod-principal/invalid/bad-principal.json b/fixtures/network.mod-principal/invalid/bad-principal.json
nnew file mode 100644
iindex 00000000..53e43c28
---- /dev/null
++++ b/fixtures/network.mod-principal/invalid/bad-principal.json
@@@ -0,0 +1 @@
++{"principal":"app:mod_01JAB2C3D4E5F6G7H8J9K0MNPQ","mod_id":"mod_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"games","runtime":"games-content@1","status":"active","requested":[],"approved":[],"pending":[],"revoked":[],"revision":1,"updated_at":"2026-09-27T23:40:00.000Z"}
ddiff --git a/fixtures/network.mod-principal/valid/active.json b/fixtures/network.mod-principal/valid/active.json
nnew file mode 100644
iindex 00000000..c1dfcd86
---- /dev/null
++++ b/fixtures/network.mod-principal/valid/active.json
@@@ -0,0 +1 @@
++{"principal":"mod:mod_01JAB2C3D4E5F6G7H8J9K0MNPQ","mod_id":"mod_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"games","runtime":"games-content@1","name":"Lanterns","version":"1.0.0","status":"active","requested":["games.world.announce","games.prop.place"],"approved":["games.world.announce"],"pending":["games.prop.place"],"revoked":[],"revision":1,"updated_at":"2026-09-27T23:40:00.000Z"}
ddiff --git a/fixtures/network.mod.grants_changed/invalid/unknown-action.json b/fixtures/network.mod.grants_changed/invalid/unknown-action.json
nnew file mode 100644
iindex 00000000..e093a95e
---- /dev/null
++++ b/fixtures/network.mod.grants_changed/invalid/unknown-action.json
@@@ -0,0 +1 @@
++{"mod_id":"mod_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"games","status":"active","approved":[],"revision":3,"change":{"action":"delete"},"by":"staff"}
ddiff --git a/fixtures/network.mod.grants_changed/valid/staff-revoke.json b/fixtures/network.mod.grants_changed/valid/staff-revoke.json
nnew file mode 100644
iindex 00000000..1521f4cc
---- /dev/null
++++ b/fixtures/network.mod.grants_changed/valid/staff-revoke.json
@@@ -0,0 +1 @@
++{"mod_id":"mod_01JAB2C3D4E5F6G7H8J9K0MNPQ","owner":"games","status":"active","approved":[],"pending":["games.prop.place"],"revision":3,"change":{"action":"revoke","capability":"games.world.announce"},"by":"staff","reason":"spawned items in a safe zone"}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex cfb86108..0247651f 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -25752,6 +25752,275 @@
}
}
},
++ "network.mod.grants_changed": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/events/payloads/network.mod.grants_changed.v1.json",
++ "title": "NetworkModGrantsChangedPayload",
++ "description": "network.mod.grants_changed v1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod principal's grants changed: registered, a capability approved or revoked, or the whole install revoked. `approved` is the complete approved set after the change, so the owning runtime sets its copy to it (idempotent by revision: an older revision changes nothing). `by` says whether the owning runtime or Network staff made the change; a runtime applies both.",
++ "type": "object",
++ "required": [
++ "mod_id",
++ "owner",
++ "status",
++ "approved",
++ "revision",
++ "change",
++ "by"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "mod_id": {
++ "type": "string",
++ "pattern": "^mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "owner": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,31}$"
++ },
++ "status": {
++ "enum": [
++ "active",
++ "revoked"
++ ]
++ },
++ "approved": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "pending": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1
++ },
++ "change": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "action"
++ ],
++ "properties": {
++ "action": {
++ "enum": [
++ "register",
++ "approve",
++ "revoke",
++ "revoke_all"
++ ]
++ },
++ "capability": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ }
++ },
++ "by": {
++ "enum": [
++ "runtime",
++ "staff"
++ ]
++ },
++ "reason": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++ }
++ },
++ "network.mod-install-request": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/mod-install-request.v1.json",
++ "title": "NetworkModInstallRequest",
++ "description": "network.mod-install-request@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a runtime (OpenVibe.Games) registers an install's mod principal, POST /internal/mods with capability mods.grant.manage. The manifest (mods.mod-manifest@1) names the requested capabilities; `approve` is the subset staff approved at install, and the rest stays pending. The runtime that registers a mod is its owner: only it (or Network staff) changes its grants. Registering the same mod again answers the existing principal.",
++ "type": "object",
++ "required": [
++ "manifest"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "manifest": {
++ "type": "object",
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ "approve": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ "actor": {
++ "type": "string",
++ "maxLength": 80,
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ }
++ }
++ }
++ },
++ "network.mod-grant-change": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/mod-grant-change.v1.json",
++ "title": "NetworkModGrantChange",
++ "description": "network.mod-grant-change@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): approve or revoke one requested capability of a mod principal, POST /internal/mods/{mod_id}/grants (the owning runtime, mods.grant.manage) or POST /api/admin/mods/{mod_id}/grants (staff.games.manage, with a reason).",
++ "type": "object",
++ "required": [
++ "capability",
++ "action"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "capability": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "action": {
++ "enum": [
++ "approve",
++ "revoke"
++ ]
++ },
++ "actor": {
++ "type": "string",
++ "maxLength": 80
++ },
++ "reason": {
++ "type": "string",
++ "maxLength": 500
++ }
++ }
++ }
++ },
++ "network.mod-principal": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/mod-principal.v1.json",
++ "title": "NetworkModPrincipal",
++ "description": "network.mod-principal@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod install's principal, `mod:<mod_id>`. Its grants are the approved subset of the capabilities its manifest requests; the rest are pending (never approved) or revoked. A revoked principal (the install ended) has no approved grants and never gets any again. The owning runtime keeps a copy of `approved` for its hot path and follows network.mod.grants_changed.",
++ "type": "object",
++ "required": [
++ "principal",
++ "mod_id",
++ "owner",
++ "runtime",
++ "status",
++ "requested",
++ "approved",
++ "pending",
++ "revoked",
++ "revision",
++ "updated_at"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "principal": {
++ "type": "string",
++ "pattern": "^mod:mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "mod_id": {
++ "type": "string",
++ "pattern": "^mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "owner": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,31}$",
++ "description": "The runtime service that registered it (games)."
++ },
++ "runtime": {
++ "type": "string",
++ "maxLength": 60,
++ "description": "The manifest's runtime, e.g. games-content@1."
++ },
++ "name": {
++ "type": "string",
++ "maxLength": 120
++ },
++ "version": {
++ "type": "string",
++ "maxLength": 40
++ },
++ "status": {
++ "enum": [
++ "active",
++ "revoked"
++ ]
++ },
++ "requested": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "approved": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "pending": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revoked": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1
++ },
++ "updated_at": {
++ "type": "string",
++ "format": "date-time"
++ }
++ }
++ }
++ },
"network.subject.merged": {
"version": "1.0.0",
"owner": "network",
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex 891bb34b..4e8b0734 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.71.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 110cd531..5b927141 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.71.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 74127485..a54deb0f 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.71.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 b2d947e9..f8c41397 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.71.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 67511132..7f7b92f3 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.71.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 6491aa7c..d2fd6476 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.71.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 65468c8e..ff752913 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.71.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 82bca9be..fa9618f8 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.71.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 c9056985..70af352c 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.71.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 df9a629d..2c532fbb 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.71.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 2d3f9a2c..42e36f9d 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.71.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 e7b36e74..ddfdd7bb 100644
---- a/generated/openapi/index.json
++++ b/generated/openapi/index.json
@@@ -96,8 +96,8 @@
"service": "network",
"name": "OpenVibe.Network",
"origin": "https://openvibe.network",
-- "operations": 20,
-- "capabilities": 17
++ "operations": 25,
++ "capabilities": 18
},
{
"service": "news",
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex 3a2ec924..5ebdd916 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.71.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 193fb32e..8efd63af 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.71.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 ade6920f..0b8e4b09 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.71.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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"
@@@ -965,6 +965,376 @@
}
}
},
++ "/internal/mods": {
++ "get": {
++ "operationId": "get_internal_mods",
++ "summary": "Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's.",
++ "description": "**mods.grant.manage** (first-party): Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's. Only the runtime that registered a mod (its owner) changes it; Network staff (staff.games.manage) can too. Every change is network.mod.grants_changed.",
++ "tags": [
++ "mods.grant"
++ ],
++ "x-openvibe-capabilities": [
++ "mods.grant.manage"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "network-admin",
++ "security": [
++ {
++ "openvibeToken": [
++ "mods.grant.manage"
++ ]
++ }
++ ],
++ "x-openvibe-input": {
++ "$ref": "#/components/schemas/network.mod-install-request.v1"
++ },
++ "parameters": [
++ {
++ "name": "manifest",
++ "in": "query",
++ "required": true,
++ "schema": {
++ "type": "object",
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ {
++ "name": "approve",
++ "in": "query",
++ "required": false,
++ "schema": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ {
++ "name": "actor",
++ "in": "query",
++ "required": false,
++ "schema": {
++ "type": "string",
++ "maxLength": 80,
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ },
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-principal.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ },
++ "post": {
++ "operationId": "post_internal_mods",
++ "summary": "Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's.",
++ "description": "**mods.grant.manage** (first-party): Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's. Only the runtime that registered a mod (its owner) changes it; Network staff (staff.games.manage) can too. Every change is network.mod.grants_changed.",
++ "tags": [
++ "mods.grant"
++ ],
++ "x-openvibe-capabilities": [
++ "mods.grant.manage"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "network-admin",
++ "security": [
++ {
++ "openvibeToken": [
++ "mods.grant.manage"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-install-request.v1"
++ }
++ }
++ }
++ },
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-principal.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/internal/mods/{mod_id}": {
++ "get": {
++ "operationId": "get_internal_mods_mod_id",
++ "summary": "Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's.",
++ "description": "**mods.grant.manage** (first-party): Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's. Only the runtime that registered a mod (its owner) changes it; Network staff (staff.games.manage) can too. Every change is network.mod.grants_changed.",
++ "tags": [
++ "mods.grant"
++ ],
++ "x-openvibe-capabilities": [
++ "mods.grant.manage"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "network-admin",
++ "security": [
++ {
++ "openvibeToken": [
++ "mods.grant.manage"
++ ]
++ }
++ ],
++ "x-openvibe-input": {
++ "$ref": "#/components/schemas/network.mod-install-request.v1"
++ },
++ "parameters": [
++ {
++ "name": "mod_id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ },
++ {
++ "name": "manifest",
++ "in": "query",
++ "required": true,
++ "schema": {
++ "type": "object",
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ {
++ "name": "approve",
++ "in": "query",
++ "required": false,
++ "schema": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ {
++ "name": "actor",
++ "in": "query",
++ "required": false,
++ "schema": {
++ "type": "string",
++ "maxLength": 80,
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ },
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-principal.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/internal/mods/{mod_id}/grants": {
++ "post": {
++ "operationId": "post_internal_mods_mod_id_grants",
++ "summary": "Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's.",
++ "description": "**mods.grant.manage** (first-party): Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's. Only the runtime that registered a mod (its owner) changes it; Network staff (staff.games.manage) can too. Every change is network.mod.grants_changed.",
++ "tags": [
++ "mods.grant"
++ ],
++ "x-openvibe-capabilities": [
++ "mods.grant.manage"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "network-admin",
++ "security": [
++ {
++ "openvibeToken": [
++ "mods.grant.manage"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-install-request.v1"
++ }
++ }
++ }
++ },
++ "parameters": [
++ {
++ "name": "mod_id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-principal.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "/internal/mods/{mod_id}/revoke": {
++ "post": {
++ "operationId": "post_internal_mods_mod_id_revoke",
++ "summary": "Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's.",
++ "description": "**mods.grant.manage** (first-party): Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's. Only the runtime that registered a mod (its owner) changes it; Network staff (staff.games.manage) can too. Every change is network.mod.grants_changed.",
++ "tags": [
++ "mods.grant"
++ ],
++ "x-openvibe-capabilities": [
++ "mods.grant.manage"
++ ],
++ "x-openvibe-visibility": [
++ "first-party"
++ ],
++ "x-openvibe-quota-class": "network-admin",
++ "security": [
++ {
++ "openvibeToken": [
++ "mods.grant.manage"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-install-request.v1"
++ }
++ }
++ }
++ },
++ "parameters": [
++ {
++ "name": "mod_id",
++ "in": "path",
++ "required": true,
++ "schema": {
++ "type": "string"
++ }
++ }
++ ],
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.mod-principal.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
"/internal/modules/{namespace}/{subject}": {
"get": {
"operationId": "get_internal_modules_namespace_subject",
@@@ -2164,6 +2534,133 @@
}
}
},
++ "network.mod-install-request.v1": {
++ "title": "NetworkModInstallRequest",
++ "description": "network.mod-install-request@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a runtime (OpenVibe.Games) registers an install's mod principal, POST /internal/mods with capability mods.grant.manage. The manifest (mods.mod-manifest@1) names the requested capabilities; `approve` is the subset staff approved at install, and the rest stays pending. The runtime that registers a mod is its owner: only it (or Network staff) changes its grants. Registering the same mod again answers the existing principal.",
++ "type": "object",
++ "required": [
++ "manifest"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "manifest": {
++ "type": "object",
++ "description": "The mod's manifest, mods.mod-manifest@1."
++ },
++ "approve": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ },
++ "description": "Approved at install; each must be requested by the manifest."
++ },
++ "actor": {
++ "type": "string",
++ "maxLength": 80,
++ "description": "Who installed it at the runtime (a subject or 'games'), for the audit row."
++ }
++ }
++ },
++ "network.mod-principal.v1": {
++ "title": "NetworkModPrincipal",
++ "description": "network.mod-principal@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod install's principal, `mod:<mod_id>`. Its grants are the approved subset of the capabilities its manifest requests; the rest are pending (never approved) or revoked. A revoked principal (the install ended) has no approved grants and never gets any again. The owning runtime keeps a copy of `approved` for its hot path and follows network.mod.grants_changed.",
++ "type": "object",
++ "required": [
++ "principal",
++ "mod_id",
++ "owner",
++ "runtime",
++ "status",
++ "requested",
++ "approved",
++ "pending",
++ "revoked",
++ "revision",
++ "updated_at"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "principal": {
++ "type": "string",
++ "pattern": "^mod:mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "mod_id": {
++ "type": "string",
++ "pattern": "^mod_[0-9A-HJKMNP-TV-Z]{26}$"
++ },
++ "owner": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,31}$",
++ "description": "The runtime service that registered it (games)."
++ },
++ "runtime": {
++ "type": "string",
++ "maxLength": 60,
++ "description": "The manifest's runtime, e.g. games-content@1."
++ },
++ "name": {
++ "type": "string",
++ "maxLength": 120
++ },
++ "version": {
++ "type": "string",
++ "maxLength": 40
++ },
++ "status": {
++ "enum": [
++ "active",
++ "revoked"
++ ]
++ },
++ "requested": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "approved": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "pending": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revoked": {
++ "type": "array",
++ "maxItems": 64,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+){2,}$"
++ }
++ },
++ "revision": {
++ "type": "integer",
++ "minimum": 1
++ },
++ "updated_at": {
++ "type": "string",
++ "format": "date-time"
++ }
++ }
++ },
"network.module-write-request.v1": {
"title": "NetworkModuleWriteRequest",
"description": "network.module-write-request@1: the request of network.modules.write on OpenVibe.Network. PUT /internal/modules/:namespace/:subject: { data } — the record's new value, validated against the namespace's schema; If-Match names the revision read (412 if it moved). DELETE /internal/modules/:namespace/:subject (204) takes no body. The answer to PUT is modules.module-record@1.",
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex 137caabf..0c648c47 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.71.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 51d18a48..5b0a2e37 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": "OpenRe.Stream API",
-- "version": "0.71.0",
-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 46b55e66..52ce14e9 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.71.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 78b694ec..5bd6e0c3 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.71.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 e1ef80e0..fc9670a9 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.71.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 c2eed1cf..263c1d54 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.71.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 346e89f8..c606ef62 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.71.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 e7ba4875..2fcf0548 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.71.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 9b35e324..31d3de6b 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.71.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 c260ca08..6a92133d 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.71.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.71.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.72.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.72.0): each operation lists the capabilities it performs; a token for the 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 ee07be75..f16b7f92 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -28804,6 +28804,101 @@ export interface NetworkAccountDataReceipt {
replaced: boolean;
}
++/** [email protected] (owner: network) */
++/**
++ * network.mod.grants_changed v1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod principal's grants changed: registered, a capability approved or revoked, or the whole install revoked. `approved` is the complete approved set after the change, so the owning runtime sets its copy to it (idempotent by revision: an older revision changes nothing). `by` says whether the owning runtime or Network staff made the change; a runtime applies both.
++ */
++export interface NetworkModGrantsChangedPayload {
++ mod_id: string;
++ owner: string;
++ status: "active" | "revoked";
++ /**
++ * @maxItems 64
++ */
++ approved: string[];
++ /**
++ * @maxItems 64
++ */
++ pending?: string[];
++ revision: number;
++ change: {
++ action: "register" | "approve" | "revoke" | "revoke_all";
++ capability?: string;
++ };
++ by: "runtime" | "staff";
++ reason?: string;
++}
++
++/** [email protected] (owner: network) */
++/**
++ * network.mod-install-request@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a runtime (OpenVibe.Games) registers an install's mod principal, POST /internal/mods with capability mods.grant.manage. The manifest (mods.mod-manifest@1) names the requested capabilities; `approve` is the subset staff approved at install, and the rest stays pending. The runtime that registers a mod is its owner: only it (or Network staff) changes its grants. Registering the same mod again answers the existing principal.
++ */
++export interface NetworkModInstallRequest {
++ /**
++ * The mod's manifest, mods.mod-manifest@1.
++ */
++ manifest: {};
++ /**
++ * Approved at install; each must be requested by the manifest.
++ *
++ * @maxItems 64
++ */
++ approve?: string[];
++ /**
++ * Who installed it at the runtime (a subject or 'games'), for the audit row.
++ */
++ actor?: string;
++}
++
++/** [email protected] (owner: network) */
++/**
++ * network.mod-grant-change@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): approve or revoke one requested capability of a mod principal, POST /internal/mods/{mod_id}/grants (the owning runtime, mods.grant.manage) or POST /api/admin/mods/{mod_id}/grants (staff.games.manage, with a reason).
++ */
++export interface NetworkModGrantChange {
++ capability: string;
++ action: "approve" | "revoke";
++ actor?: string;
++ reason?: string;
++}
++
++/** [email protected] (owner: network) */
++/**
++ * network.mod-principal@1 (OpenVibe.Network; roadmap WS-M task 3, ADR-013): a mod install's principal, `mod:<mod_id>`. Its grants are the approved subset of the capabilities its manifest requests; the rest are pending (never approved) or revoked. A revoked principal (the install ended) has no approved grants and never gets any again. The owning runtime keeps a copy of `approved` for its hot path and follows network.mod.grants_changed.
++ */
++export interface NetworkModPrincipal {
++ principal: string;
++ mod_id: string;
++ /**
++ * The runtime service that registered it (games).
++ */
++ owner: string;
++ /**
++ * The manifest's runtime, e.g. games-content@1.
++ */
++ runtime: string;
++ name?: string;
++ version?: string;
++ status: "active" | "revoked";
++ /**
++ * @maxItems 64
++ */
++ requested: string[];
++ /**
++ * @maxItems 64
++ */
++ approved: string[];
++ /**
++ * @maxItems 64
++ */
++ pending: string[];
++ /**
++ * @maxItems 64
++ */
++ revoked: string[];
++ revision: number;
++ updated_at: string;
++}
++
/** [email protected] (owner: network) */
/**
* network.subject.merged v1 (OpenVibe.Network; roadmap WS-B task 5, ADR-029). Two accounts became one: `from`, the folded-in subject, is now an alias of `into`, the survivor, which keeps its subject, username, profile and settings. Network has already moved what it owns (linked providers, sessions, OAuth grants, developer projects, OpenCoins and user modules) in the transaction that writes this event to its outbox. Every service that stores subjects repoints its own rows from `from` to `into` in its own transaction and keeps no copy under `from`; a row it cannot move (a unique conflict, such as both accounts following the same channel) keeps the survivor's row and drops the other, as a counted, logged outcome. Until a service has applied it, its rows stay under `from`, which still resolves to `into` through Network's aliases. Apply once per merge_id. Envelope: subject { type: user, id: <into> }, visibility internal, actor the person who merged (or the staff member, for an account-recovery merge).
ddiff --git a/manifests/capabilities/mods.grant.manage.json b/manifests/capabilities/mods.grant.manage.json
iindex 9ddcb238..4cb5c04f 100644
---- a/manifests/capabilities/mods.grant.manage.json
++++ b/manifests/capabilities/mods.grant.manage.json
@@@ -2,13 +2,26 @@
"id": "mods.grant.manage",
"version": "1.0",
"owner": "network",
-- "status": "planned",
++ "status": "active",
"visibility": "first-party",
-- "description": "Planned (ADR-013, grants in Network): create the `mod` principal (mod:mod_<ULID>) for an install and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants are checked like any other principal's. Until Network implements it, each runtime keeps the approved subset itself (OpenVibe.Games: mod_grants).",
-- "inputSchema": "mods.mod-manifest@1",
-- "permissions": ["network:grants:admin"],
-- "resourceConstraints": ["none"],
++ "description": "Register a mod install's principal (mod:<mod_id>, ADR-013) and approve or revoke the subset of its manifest's requested capabilities, so a mod's grants live in Network like any other principal's. Only the runtime that registered a mod (its owner) changes it; Network staff (staff.games.manage) can too. Every change is network.mod.grants_changed.",
++ "inputSchema": "network.mod-install-request@1",
++ "permissions": [
++ "network:grants:admin"
++ ],
++ "resourceConstraints": [
++ "owner"
++ ],
"quotaClass": "network-admin",
-- "events": [],
-- "implementedBy": []
++ "events": [
++ "network.mod.grants_changed"
++ ],
++ "implementedBy": [
++ "POST /internal/mods",
++ "GET /internal/mods",
++ "GET /internal/mods/:mod_id",
++ "POST /internal/mods/:mod_id/grants",
++ "POST /internal/mods/:mod_id/revoke"
++ ],
++ "outputSchema": "network.mod-principal@1"
}
ddiff --git a/manifests/services/games.json b/manifests/services/games.json
iindex dee27db9..472bcbe8 100644
---- a/manifests/services/games.json
++++ b/manifests/services/games.json
@@@ -49,6 +49,7 @@
"eventsConsumed": [
"network.account.deleted",
"network.account.export_requested",
++ "network.mod.grants_changed",
"network.user.token_valid_after"
],
"namespacesOwned": [
ddiff --git a/manifests/services/network.json b/manifests/services/network.json
iindex 2c92ff90..e613ae3b 100644
---- a/manifests/services/network.json
++++ b/manifests/services/network.json
@@@ -54,6 +54,8 @@
"network.status.incident"
],
"eventsProduced": [
++ "network.account.deleted",
++ "network.account.export_requested",
"network.app.created",
"network.app.revoked",
"network.block.changed",
@@@ -61,13 +63,12 @@
"network.credential.rotated",
"network.follow.created",
"network.follow.deleted",
-- "network.subject.merged",
-- "network.account.export_requested",
-- "network.account.deleted",
"network.grant.changed",
++ "network.mod.grants_changed",
"network.module.updated",
"network.notification.created",
"network.principal_grant.changed",
++ "network.subject.merged",
"network.user.token_valid_after",
"network.user.updated"
],
ddiff --git a/package.json b/package.json
iindex 6ad8b7ff..ac295997 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.71.0",
++ "version": "0.72.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",