openvibers/openvibe.contracts Commits

0.257.0: labels and choices (L1) — content labels and viewer prefs (#265)

OP OpenVibers committed 13 days ago · 08cf434d53 · 62 files, +566 −81

* 0.257.0: labels and choices (L1) — the content labels and the viewer's prefs

Labels are choices, not bans: a creator labels a stream, VOD, clip, picture or post; the AI may only suggest one;
three viewer suggestions or a moderator put one on; and each viewer chooses show, blur or hide per label.

- common.content-labels@1: the six labels (nudity, language, graphic, 18+, flashing, spoilers) and the shape
  { labels, suggested }. A suggestion is stored as suggested and never applied.
- network.label-prefs@1: one choice per label (show, blur, hide) in Network site prefs, one setting across sites.
  The web default is show; the native apps start nudity and 18+ at hide until the person turns them on.
- labels is exported from the package (LABELS, CHOICES, INFO, defaults), and test/content-labels.test.js holds
  every label list to the one list, checks the fixtures and the suggestion rule.

* 0.258.0: labels and choices (L1) — content labels and viewer prefs

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex d19c24da..6c1ae236 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -1,5 +1,20 @@
# Changelog
++## 0.258.0 — 2026-10-31
++
++- **Labels and choices** (L1, `OpenVibe_Consent_Plan_2026-10-31.md` §"Labels and choices"): light rules, not bans.
++ - **`common.content-labels@1`:** the six labels (`nudity`, `language`, `graphic`, `18+`, `flashing`, `spoilers`)
++ and the shape `{ labels, suggested }` for a stream, VOD, clip, picture or post. `labels` are in force (the
++ creator, a moderator, or three viewer suggestions); `suggested` is what the AI or a viewer proposed and nobody
++ confirmed, so a suggestion never applies itself and never takes anything down.
++ - **`network.label-prefs@1`:** one person's choice per label — `show`, `blur` (until tapped) or `hide` — in
++ Network's site prefs, so one setting covers every site. The web default is `show`; the native apps start
++ `nudity` and `18+` at hide until the person turns them on in their web settings. The home page shows nothing
++ labelled `18+` whatever the prefs say.
++ - **`labels`** is exported from the package (`LABELS`, `CHOICES`, `INFO`, `defaults()`), so a service reads the
++ one list instead of copying it. `test/content-labels.test.js` checks that every list matches and that the
++ fixtures hold the rules the schemas cannot say.
++
## 0.257.0 — 2026-10-31
- **"Your AI": a person's own provider keys, and how their runs route** (L36 Y1/Y3/Y8; OpenVibe.AI). Five additive
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex 0829fbd1..5d0b64e2 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -209,6 +209,15 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "common.content-labels",
++ "version": "1.0.0",
++ "owner": "contracts",
++ "schema": "common/content-labels.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "common.moderation-action",
"version": "1.0.0",
@@@ -7761,6 +7770,15 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "network.label-prefs",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "network/label-prefs.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "network.consent.changed",
"version": "1.0.0",
ddiff --git a/contracts/common/content-labels.v1.json b/contracts/common/content-labels.v1.json
nnew file mode 100644
iindex 00000000..8b871a80
---- /dev/null
++++ b/contracts/common/content-labels.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/common/content-labels.v1.json",
++ "title": "ContentLabels",
++ "description": "common.content-labels@1 (L1, labels and choices, 2026-10-31): what a stream, VOD, clip, picture or post is labelled as, and what the AI has suggested but the creator has not confirmed. Labels are choices, never bans: a label never hides content from the person who posted it, and it never hides content from a viewer whose label preferences show it. A creator sets a label; the AI may only suggest one (a suggestion the creator confirms, never a takedown); three viewer suggestions or a moderator put one on. The label set is one list everywhere: nudity, language, graphic, 18+, flashing and spoilers.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["labels", "suggested"],
++ "properties": {
++ "labels": {
++ "type": "array",
++ "maxItems": 6,
++ "uniqueItems": true,
++ "items": { "$ref": "#/$defs/label" },
++ "description": "The labels in force: set by the creator, or by a moderator, or by three viewer suggestions. A label never hides anything by itself; each viewer's prefs decide (network.label-prefs@1)."
++ },
++ "suggested": {
++ "type": "array",
++ "maxItems": 6,
++ "uniqueItems": true,
++ "items": { "$ref": "#/$defs/label" },
++ "description": "What the AI or a viewer suggested and nobody confirmed yet. Stored as a suggestion and never applied: a label in this list changes nothing for anyone until the creator (or a moderator) puts it in labels."
++ }
++ },
++ "$defs": {
++ "label": {
++ "enum": ["nudity", "language", "graphic", "18+", "flashing", "spoilers"],
++ "description": "nudity: nudity or sexual content; language: strong language; graphic: graphic violence or injury; 18+: adults only; flashing: flashing lights or rapid motion; spoilers: spoils a story."
++ }
++ }
++}
ddiff --git a/contracts/network/label-prefs.v1.json b/contracts/network/label-prefs.v1.json
nnew file mode 100644
iindex 00000000..222f8a07
---- /dev/null
++++ b/contracts/network/label-prefs.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/label-prefs.v1.json",
++ "title": "NetworkLabelPrefs",
++ "description": "network.label-prefs@1 (L1, labels and choices, 2026-10-31): what one person sees for each content label, on every OpenVibe site. One setting per label, stored in Network's site prefs, so the choice follows the account across Stream, Video, Pics and every other site. GET and PUT /api/v1/me/label-prefs; the response and the request are this shape. The web default is show for every label; the native apps hide nudity and 18+ until the person turns them on here (pinned by the app stores' user-content rules). The home page shows nothing labelled 18+ whatever the prefs say: it is the owner's one clean page.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["prefs"],
++ "properties": {
++ "prefs": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["nudity", "language", "graphic", "18+", "flashing", "spoilers"],
++ "properties": {
++ "nudity": { "$ref": "#/$defs/choice" },
++ "language": { "$ref": "#/$defs/choice" },
++ "graphic": { "$ref": "#/$defs/choice" },
++ "18+": { "$ref": "#/$defs/choice" },
++ "flashing": { "$ref": "#/$defs/choice" },
++ "spoilers": { "$ref": "#/$defs/choice" }
++ },
++ "description": "One choice for every label. A missing label is not a choice: a client asks Network and gets all six."
++ }
++ },
++ "$defs": {
++ "choice": {
++ "enum": ["show", "blur", "hide"],
++ "description": "show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them."
++ }
++ }
++}
ddiff --git a/fixtures/common.content-labels/invalid/duplicate-label.json b/fixtures/common.content-labels/invalid/duplicate-label.json
nnew file mode 100644
iindex 00000000..c46dec76
---- /dev/null
++++ b/fixtures/common.content-labels/invalid/duplicate-label.json
@@@ -0,0 +1,4 @@
++{
++ "labels": ["nudity", "nudity"],
++ "suggested": []
++}
ddiff --git a/fixtures/common.content-labels/invalid/missing-suggested.json b/fixtures/common.content-labels/invalid/missing-suggested.json
nnew file mode 100644
iindex 00000000..71c73191
---- /dev/null
++++ b/fixtures/common.content-labels/invalid/missing-suggested.json
@@@ -0,0 +1,3 @@
++{
++ "labels": ["nudity"]
++}
ddiff --git a/fixtures/common.content-labels/invalid/unknown-label.json b/fixtures/common.content-labels/invalid/unknown-label.json
nnew file mode 100644
iindex 00000000..17051aac
---- /dev/null
++++ b/fixtures/common.content-labels/invalid/unknown-label.json
@@@ -0,0 +1,4 @@
++{
++ "labels": ["gore"],
++ "suggested": []
++}
ddiff --git a/fixtures/common.content-labels/valid/ai-suggestion.json b/fixtures/common.content-labels/valid/ai-suggestion.json
nnew file mode 100644
iindex 00000000..a5d0edd8
---- /dev/null
++++ b/fixtures/common.content-labels/valid/ai-suggestion.json
@@@ -0,0 +1,4 @@
++{
++ "labels": ["18+"],
++ "suggested": ["nudity"]
++}
ddiff --git a/fixtures/common.content-labels/valid/creator-vod.json b/fixtures/common.content-labels/valid/creator-vod.json
nnew file mode 100644
iindex 00000000..c4d941db
---- /dev/null
++++ b/fixtures/common.content-labels/valid/creator-vod.json
@@@ -0,0 +1,4 @@
++{
++ "labels": ["graphic", "language"],
++ "suggested": []
++}
ddiff --git a/fixtures/common.content-labels/valid/nothing.json b/fixtures/common.content-labels/valid/nothing.json
nnew file mode 100644
iindex 00000000..d5f23659
---- /dev/null
++++ b/fixtures/common.content-labels/valid/nothing.json
@@@ -0,0 +1,4 @@
++{
++ "labels": [],
++ "suggested": []
++}
ddiff --git a/fixtures/network.label-prefs/invalid/extra-label.json b/fixtures/network.label-prefs/invalid/extra-label.json
nnew file mode 100644
iindex 00000000..cf3c242f
---- /dev/null
++++ b/fixtures/network.label-prefs/invalid/extra-label.json
@@@ -0,0 +1,11 @@
++{
++ "prefs": {
++ "nudity": "show",
++ "language": "show",
++ "graphic": "show",
++ "18+": "show",
++ "flashing": "show",
++ "spoilers": "show",
++ "gore": "show"
++ }
++}
ddiff --git a/fixtures/network.label-prefs/invalid/missing-label.json b/fixtures/network.label-prefs/invalid/missing-label.json
nnew file mode 100644
iindex 00000000..3e791279
---- /dev/null
++++ b/fixtures/network.label-prefs/invalid/missing-label.json
@@@ -0,0 +1,9 @@
++{
++ "prefs": {
++ "nudity": "show",
++ "language": "show",
++ "graphic": "show",
++ "flashing": "show",
++ "spoilers": "show"
++ }
++}
ddiff --git a/fixtures/network.label-prefs/invalid/unknown-choice.json b/fixtures/network.label-prefs/invalid/unknown-choice.json
nnew file mode 100644
iindex 00000000..c8c431b7
---- /dev/null
++++ b/fixtures/network.label-prefs/invalid/unknown-choice.json
@@@ -0,0 +1,10 @@
++{
++ "prefs": {
++ "nudity": "sometimes",
++ "language": "show",
++ "graphic": "show",
++ "18+": "show",
++ "flashing": "show",
++ "spoilers": "show"
++ }
++}
ddiff --git a/fixtures/network.label-prefs/valid/all-show.json b/fixtures/network.label-prefs/valid/all-show.json
nnew file mode 100644
iindex 00000000..fe55ef60
---- /dev/null
++++ b/fixtures/network.label-prefs/valid/all-show.json
@@@ -0,0 +1,10 @@
++{
++ "prefs": {
++ "nudity": "show",
++ "language": "show",
++ "graphic": "show",
++ "18+": "show",
++ "flashing": "show",
++ "spoilers": "show"
++ }
++}
ddiff --git a/fixtures/network.label-prefs/valid/mixed.json b/fixtures/network.label-prefs/valid/mixed.json
nnew file mode 100644
iindex 00000000..f0ef196e
---- /dev/null
++++ b/fixtures/network.label-prefs/valid/mixed.json
@@@ -0,0 +1,10 @@
++{
++ "prefs": {
++ "nudity": "hide",
++ "language": "show",
++ "graphic": "blur",
++ "18+": "hide",
++ "flashing": "blur",
++ "spoilers": "blur"
++ }
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex 98b4c7fe..0875ac75 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -2931,6 +2931,56 @@
]
}
},
++ "common.content-labels": {
++ "version": "1.0.0",
++ "owner": "contracts",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/common/content-labels.v1.json",
++ "title": "ContentLabels",
++ "description": "common.content-labels@1 (L1, labels and choices, 2026-10-31): what a stream, VOD, clip, picture or post is labelled as, and what the AI has suggested but the creator has not confirmed. Labels are choices, never bans: a label never hides content from the person who posted it, and it never hides content from a viewer whose label preferences show it. A creator sets a label; the AI may only suggest one (a suggestion the creator confirms, never a takedown); three viewer suggestions or a moderator put one on. The label set is one list everywhere: nudity, language, graphic, 18+, flashing and spoilers.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "labels",
++ "suggested"
++ ],
++ "properties": {
++ "labels": {
++ "type": "array",
++ "maxItems": 6,
++ "uniqueItems": true,
++ "items": {
++ "$ref": "#/$defs/label"
++ },
++ "description": "The labels in force: set by the creator, or by a moderator, or by three viewer suggestions. A label never hides anything by itself; each viewer's prefs decide (network.label-prefs@1)."
++ },
++ "suggested": {
++ "type": "array",
++ "maxItems": 6,
++ "uniqueItems": true,
++ "items": {
++ "$ref": "#/$defs/label"
++ },
++ "description": "What the AI or a viewer suggested and nobody confirmed yet. Stored as a suggestion and never applied: a label in this list changes nothing for anyone until the creator (or a moderator) puts it in labels."
++ }
++ },
++ "$defs": {
++ "label": {
++ "enum": [
++ "nudity",
++ "language",
++ "graphic",
++ "18+",
++ "flashing",
++ "spoilers"
++ ],
++ "description": "nudity: nudity or sexual content; language: strong language; graphic: graphic violence or injury; 18+: adults only; flashing: flashing lights or rapid motion; spoilers: spoils a story."
++ }
++ }
++ }
++ },
"common.moderation-action": {
"version": "1.0.0",
"owner": "network",
@@@ -88048,6 +88098,67 @@
}
}
},
++ "network.label-prefs": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/label-prefs.v1.json",
++ "title": "NetworkLabelPrefs",
++ "description": "network.label-prefs@1 (L1, labels and choices, 2026-10-31): what one person sees for each content label, on every OpenVibe site. One setting per label, stored in Network's site prefs, so the choice follows the account across Stream, Video, Pics and every other site. GET and PUT /api/v1/me/label-prefs; the response and the request are this shape. The web default is show for every label; the native apps hide nudity and 18+ until the person turns them on here (pinned by the app stores' user-content rules). The home page shows nothing labelled 18+ whatever the prefs say: it is the owner's one clean page.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "prefs"
++ ],
++ "properties": {
++ "prefs": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "nudity",
++ "language",
++ "graphic",
++ "18+",
++ "flashing",
++ "spoilers"
++ ],
++ "properties": {
++ "nudity": {
++ "$ref": "#/$defs/choice"
++ },
++ "language": {
++ "$ref": "#/$defs/choice"
++ },
++ "graphic": {
++ "$ref": "#/$defs/choice"
++ },
++ "18+": {
++ "$ref": "#/$defs/choice"
++ },
++ "flashing": {
++ "$ref": "#/$defs/choice"
++ },
++ "spoilers": {
++ "$ref": "#/$defs/choice"
++ }
++ },
++ "description": "One choice for every label. A missing label is not a choice: a client asks Network and gets all six."
++ }
++ },
++ "$defs": {
++ "choice": {
++ "enum": [
++ "show",
++ "blur",
++ "hide"
++ ],
++ "description": "show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them."
++ }
++ }
++ }
++ },
"network.consent.changed": {
"version": "1.0.0",
"owner": "network",
ddiff --git a/generated/openapi/actor.json b/generated/openapi/actor.json
iindex 2097034b..025e58f1 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.257.0",
-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 220f634c..f4cd383e 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.257.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/bench.json b/generated/openapi/bench.json
iindex de603d29..a4e92f93 100644
---- a/generated/openapi/bench.json
++++ b/generated/openapi/bench.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bench API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 8ef14b0f..14af5709 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.257.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 d8c0a5a4..69d960eb 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.257.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 6cf642bb..9fe78fe9 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.257.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 a0635a82..e40734cf 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.257.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 63a23b51..2044f5d1 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.257.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 b0cd4a9c..bf9e4730 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.257.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 242e91c6..b6fe2443 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.257.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 39af9ad3..0d912481 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.257.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/domains.json b/generated/openapi/domains.json
iindex 784be030..e9eb3763 100644
---- a/generated/openapi/domains.json
++++ b/generated/openapi/domains.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Domains API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 53b587c4..67f7221b 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.257.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 cbcca0f9..a604d11e 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.257.0",
-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 92682df1..1a4ef4bc 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.257.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 6e8d1ace..0e950c4d 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.257.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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/inventory.json b/generated/openapi/inventory.json
iindex 77bafba7..40374439 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.257.0",
-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 c797e1de..a77785d8 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.257.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/media-hub.json b/generated/openapi/media-hub.json
iindex 170bcbdd..6da98ca8 100644
---- a/generated/openapi/media-hub.json
++++ b/generated/openapi/media-hub.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.MediaHub API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 8f6f7766..f87b337a 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.257.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 c68efa1f..bb82d3b5 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.257.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 88dec559..e4d9f9cc 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.257.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 196fd0e7..92981815 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.257.0",
-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/play.json b/generated/openapi/play.json
iindex 087833bd..6e724e54 100644
---- a/generated/openapi/play.json
++++ b/generated/openapi/play.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Play API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/quest.json b/generated/openapi/quest.json
iindex b0417f21..e7d0cb37 100644
---- a/generated/openapi/quest.json
++++ b/generated/openapi/quest.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Quest API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 b7c46d1b..45f0e2c3 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.257.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 d4c5f572..eb05b1e7 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.257.0",
-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 689aeff9..5ad146fd 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.257.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 3b31c30b..81006548 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.257.0",
-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 a276c38b..551f9eb8 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.257.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/space.json b/generated/openapi/space.json
iindex 719cc697..2631c602 100644
---- a/generated/openapi/space.json
++++ b/generated/openapi/space.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Space API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 4616ccc0..33a3ea5f 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.257.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 8fb822e4..9e74a412 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.257.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 43d81ca1..4154fdc7 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.257.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 c34188c3..f200926f 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.257.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/vision.json b/generated/openapi/vision.json
iindex bf45596f..d91a9614 100644
---- a/generated/openapi/vision.json
++++ b/generated/openapi/vision.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Vision API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 7c833c00..62a70e93 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.257.0",
-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 c739355a..c8535694 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.257.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/work.json b/generated/openapi/work.json
iindex 5faa7c7f..04f39fbb 100644
---- a/generated/openapi/work.json
++++ b/generated/openapi/work.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Work API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/zone.json b/generated/openapi/zone.json
iindex eb36fd51..788bf851 100644
---- a/generated/openapi/zone.json
++++ b/generated/openapi/zone.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Zone API",
-- "version": "0.257.0",
-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.257.0): each operation lists the capabilities it performs; a token for 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.258.0",
++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.258.0): each operation lists the capabilities it performs; a token for 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 f4d33819..9b03f4da 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -4674,6 +4674,89 @@ export type ConfigSnapshot = {
copied_from?: number | null;
};
++/** [email protected] (owner: contracts) */
++/**
++ * common.content-labels@1 (L1, labels and choices, 2026-10-31): what a stream, VOD, clip, picture or post is labelled as, and what the AI has suggested but the creator has not confirmed. Labels are choices, never bans: a label never hides content from the person who posted it, and it never hides content from a viewer whose label preferences show it. A creator sets a label; the AI may only suggest one (a suggestion the creator confirms, never a takedown); three viewer suggestions or a moderator put one on. The label set is one list everywhere: nudity, language, graphic, 18+, flashing and spoilers.
++ */
++export interface ContentLabels {
++ /**
++ * The labels in force: set by the creator, or by a moderator, or by three viewer suggestions. A label never hides anything by itself; each viewer's prefs decide (network.label-prefs@1).
++ *
++ * @maxItems 6
++ */
++ labels:
++ | []
++ | ["nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ];
++ /**
++ * What the AI or a viewer suggested and nobody confirmed yet. Stored as a suggestion and never applied: a label in this list changes nothing for anyone until the creator (or a moderator) puts it in labels.
++ *
++ * @maxItems 6
++ */
++ suggested:
++ | []
++ | ["nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ]
++ | [
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers",
++ "nudity" | "language" | "graphic" | "18+" | "flashing" | "spoilers"
++ ];
++}
++
/** [email protected] (owner: network) */
/**
* common.moderation-action@1 (ADR-022, roadmap WS-D task 1): one staff or moderator action on someone else's content or account, as a service reports it to OpenVibe.Network's moderation audit log. The payload of every <service>.moderation.action event that has no older shape of its own (tools, games, wiki, blog, news, reviews, deals, coupons, trade, codes); modelled on community.moderation.action@1. Written to the service's outbox in the transaction that performs the action. A person acting on their own content is not moderation and is not reported. Envelope: subject { type: moderation_action, id: <target type>:<target id> }, visibility internal, actor the staff member. Never carries the content itself, a secret or an address.
@@@ -274399,6 +274482,42 @@ export interface NetworkConsentCheckResult {
checked_at: string;
}
++/** [email protected] (owner: network) */
++/**
++ * network.label-prefs@1 (L1, labels and choices, 2026-10-31): what one person sees for each content label, on every OpenVibe site. One setting per label, stored in Network's site prefs, so the choice follows the account across Stream, Video, Pics and every other site. GET and PUT /api/v1/me/label-prefs; the response and the request are this shape. The web default is show for every label; the native apps hide nudity and 18+ until the person turns them on here (pinned by the app stores' user-content rules). The home page shows nothing labelled 18+ whatever the prefs say: it is the owner's one clean page.
++ */
++export interface NetworkLabelPrefs {
++ /**
++ * One choice for every label. A missing label is not a choice: a client asks Network and gets all six.
++ */
++ prefs: {
++ /**
++ * show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them.
++ */
++ nudity: "show" | "blur" | "hide";
++ /**
++ * show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them.
++ */
++ language: "show" | "blur" | "hide";
++ /**
++ * show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them.
++ */
++ graphic: "show" | "blur" | "hide";
++ /**
++ * show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them.
++ */
++ "18+": "show" | "blur" | "hide";
++ /**
++ * show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them.
++ */
++ flashing: "show" | "blur" | "hide";
++ /**
++ * show: as it is; blur: covered until the person taps Show; hide: not shown, and not in search results for that person. A label the person posted is always shown to them.
++ */
++ spoilers: "show" | "blur" | "hide";
++ };
++}
++
/** [email protected] (owner: network) */
/**
* network.consent.changed v1 (OpenVibe.Network, L24): a person turned a purpose on or off, an app's grant was revoked, or a choice expired. A service that caches consent answers drops that subject's answers for the purpose at once; one that is running a use for the subject (a dataset build, a recognition, an AI text) checks again before it goes on. The payload names the change and never the content it covers.
ddiff --git a/index.js b/index.js
iindex 4b6a0d26..056f6c7e 100644
---- a/index.js
++++ b/index.js
@@@ -30,5 +30,6 @@ module.exports = {
usage: require('./lib/usage'),
resources: require('./lib/resources'),
staff: require('./lib/staff'),
++ labels: require('./lib/labels'),
openapi: require('./lib/openapi'),
};
ddiff --git a/lib/labels.js b/lib/labels.js
nnew file mode 100644
iindex 00000000..6a27b52d
---- /dev/null
++++ b/lib/labels.js
@@@ -0,0 +1,31 @@
++'use strict';
++/**
++ * The six content labels (L1, labels and choices, 2026-10-31) and the three viewer choices.
++ *
++ * One list for every contract, service and SDK: nudity, language, graphic, 18+, flashing and spoilers.
++ * Labels are choices, not bans — a creator sets them, the AI may suggest them, three viewer suggestions
++ * or a moderator put one on, and each viewer's network.label-prefs@1 decides what they see. The native
++ * apps start nudity and 18+ at hide until the person turns them on in their web settings.
++ */
++const LABELS = Object.freeze(['nudity', 'language', 'graphic', '18+', 'flashing', 'spoilers']);
++
++/** What a viewer may choose for each label (network.label-prefs@1). */
++const CHOICES = Object.freeze(['show', 'blur', 'hide']);
++
++/** The plain words the account page and every chip use. Copy, not markup: the API carries it too. */
++const INFO = Object.freeze([
++ Object.freeze({ id: 'nudity', title: 'Nudity', description: 'Nudity and sexual content.' }),
++ Object.freeze({ id: 'language', title: 'Strong language', description: 'Swearing and strong language.' }),
++ Object.freeze({ id: 'graphic', title: 'Graphic violence', description: 'Graphic violence or injury.' }),
++ Object.freeze({ id: '18+', title: '18+', description: 'For adults only.' }),
++ Object.freeze({ id: 'flashing', title: 'Flashing lights', description: 'Flashing lights or rapid motion.' }),
++ Object.freeze({ id: 'spoilers', title: 'Spoilers', description: 'Gives away a story.' }),
++]);
++
++/** The web default, and the value an unset label means on OpenVibe. */
++const DEFAULT = 'show';
++
++/** All six at the default, as network.label-prefs@1's `prefs`. */
++const defaults = () => Object.fromEntries(LABELS.map((label) => [label, DEFAULT]));
++
++module.exports = { LABELS, CHOICES, INFO, DEFAULT, defaults };
ddiff --git a/package.json b/package.json
iindex 3695f463..0bc02a05 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.257.0",
++ "version": "0.258.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",
ddiff --git a/test/content-labels.test.js b/test/content-labels.test.js
nnew file mode 100644
iindex 00000000..56679731
---- /dev/null
++++ b/test/content-labels.test.js
@@@ -0,0 +1,53 @@
++'use strict';
++// common.content-labels@1 and network.label-prefs@1 (L1, labels and choices, 2026-10-31). The schemas carry the
++// shapes; the rules they cannot say are checked here: one label list everywhere (contracts, prefs and the JS
++// helper), one choice list, the AI's suggestion stored as suggested and never applied, and the fixtures.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++const c = require('..');
++
++const ROOT = path.join(__dirname, '..');
++const schema = (f) => JSON.parse(fs.readFileSync(path.join(ROOT, 'contracts', f), 'utf8'));
++const fx = (id, kind, f) => JSON.parse(fs.readFileSync(path.join(ROOT, 'fixtures', id, kind, f), 'utf8'));
++
++const LABELS = ['nudity', 'language', 'graphic', '18+', 'flashing', 'spoilers'];
++const CHOICES = ['show', 'blur', 'hide'];
++
++const content = schema('common/content-labels.v1.json');
++const prefs = schema('network/label-prefs.v1.json');
++
++// One label list in every contract, and the same list in the package's helper, so a service reads it from one place.
++assert.deepStrictEqual(content.$defs.label.enum, LABELS, 'content-labels lists the six labels');
++assert.deepStrictEqual(content.properties.labels.items.$ref, '#/$defs/label', 'labels are the shared enum');
++assert.deepStrictEqual(content.properties.suggested.items.$ref, '#/$defs/label', 'suggested is the same enum');
++assert.deepStrictEqual(Object.keys(prefs.properties.prefs.properties), LABELS, 'label-prefs has one choice per label');
++assert.deepStrictEqual(prefs.properties.prefs.required, LABELS, 'label-prefs always answers all six');
++assert.deepStrictEqual(prefs.$defs.choice.enum, CHOICES, 'the choices are show, blur and hide');
++assert.deepStrictEqual(c.labels.LABELS, LABELS, 'the helper lists the same labels');
++assert.deepStrictEqual(c.labels.CHOICES, CHOICES, 'the helper lists the same choices');
++assert.deepStrictEqual(c.labels.INFO.map((x) => x.id), LABELS, 'the plain words cover every label');
++assert.deepStrictEqual(c.labels.defaults(), Object.fromEntries(LABELS.map((l) => [l, 'show'])), 'the web default is show');
++
++// A suggestion changes nothing: the fixture keeps the label out of `labels`, and an unknown label or choice never validates.
++const ai = fx('common.content-labels', 'valid', 'ai-suggestion.json');
++assert.ok(ai.suggested.includes('nudity') && !ai.labels.includes('nudity'), 'the AI suggestion is stored as suggested, never applied');
++assert.strictEqual(c.validate('common.content-labels@1', ai).valid, true, 'an AI suggestion is a valid content-labels');
++assert.strictEqual(c.validate('common.content-labels@1', { labels: ['nudity', 'nudity'], suggested: [] }).valid, false, 'a label is listed once');
++assert.strictEqual(c.validate('network.label-prefs@1', { prefs: { ...c.labels.defaults(), nudity: 'hide' } }).valid, true, 'hide is a choice');
++
++// The fixtures: each valid one validates, each invalid one does not.
++for (const id of ['common.content-labels', 'network.label-prefs']) {
++ for (const kind of ['valid', 'invalid']) {
++ for (const f of fs.readdirSync(path.join(ROOT, 'fixtures', id, kind))) {
++ const r = c.validate(`${id}@1`, fx(id, kind, f));
++ assert.strictEqual(r.valid, kind === 'valid', `${id} ${kind}/${f}: ${JSON.stringify(r.errors)}`);
++ }
++ }
++}
++
++// The catalog lists both contracts, and the enum is the same shape in the package a service pins.
++assert.ok(c.catalog.some((x) => x.id === 'common.content-labels' && x.version === '1.0.0'), 'the catalog lists common.content-labels@1');
++assert.ok(c.catalog.some((x) => x.id === 'network.label-prefs' && x.version === '1.0.0'), 'the catalog lists network.label-prefs@1');
++
++console.log('common.content-labels@1 and network.label-prefs@1: one label and choice list, suggestions never applied, fixtures');
ddiff --git a/test/run.js b/test/run.js
iindex d7fbf634..464e1f28 100644
---- a/test/run.js
++++ b/test/run.js
@@@ -929,6 +929,8 @@ sub(path.join(__dirname, 'resources.test.js'));
// The wait record (plan A2): a wait is a record, not a running loop.
sub(path.join(__dirname, 'actor-wait.test.js'));
sub(path.join(__dirname, 'network-consent.test.js'));
++// Labels and choices (L1): one label list, one choice list, and the AI's suggestion stored as suggested.
++sub(path.join(__dirname, 'content-labels.test.js'));
// Documentation currency (roadmap WS-U task 3): a placeholder service with no repository yet is skipped, not a gap.
sub(path.join(__dirname, 'docs-currency.test.js'));