openvibers/openvibe.contracts Commits
Contracts 0.121.0: ADR-054 — the OpenVibe inventory authority (kinds, definitions, instances, equipped, ledger); its planned service, capabilities, schemas and events (plan T21 step 1) (#68)
Changes
@@@ -4,6 +4,24 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) thfrom `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,the notes were in the tag and commit messages (`git tag -n1`).++## 0.121.0 — 2026-10-09++++**The OpenVibe inventory, decided (ADR-054, plan T21 step 1).** A new authority, OpenVibe.Inventory, will own items++across the network: kinds, definitions, instances, the equipped set and an append-only ledger.++- `docs/adr/ADR-054-inventory-authority.md` (accepted):++ - service `inventory`, `ov_inventory`, loopback 5030, `inventory.openvibe.network`;++ - issuers grant within their namespace;++ - nothing is sold, bought, traded or converted until a later money ADR (ADR-012, ADR-025);++ - Live's cosmetics become the first kinds, migrated convert-verify-delete.++- `manifests/services/inventory.json` (placeholder), with seven planned capabilities: `inventory.item.read`,++ `inventory.item.list`, `inventory.equip.manage`, `inventory.item.grant`, `inventory.item.consume`,++ `inventory.definition.manage` and `inventory.definition.review`.++- Schemas, with fixtures: `inventory.kind@1`, `inventory.definition@1`, `inventory.instance@1`,++ `inventory.inventory@1`, `inventory.equipped@1`, `inventory.equipped-batch@1`, `inventory.grant-request@1`,++ `inventory.equip-request@1` and `inventory.definition-request@1`.++- Events: `inventory.item.granted`, `inventory.item.consumed`, `inventory.item.revoked`, `inventory.item.equipped`,++ `inventory.item.unequipped` and `inventory.definition.published`.++## 0.120.0 — 2026-10-09**Account export and deletion everywhere a person has rows.** Nine more services declare the two account events.@@@ -6398,6 +6398,156 @@"visibility": "public","compatibility": "backward","status": "active"++ },++ {++ "id": "inventory.kind",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/kind.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.definition",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/definition.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.instance",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/instance.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.inventory",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/inventory.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.equipped",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/equipped.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.equipped-batch",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/equipped-batch.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.grant-request",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/grant-request.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.equip-request",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/equip-request.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.definition-request",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "inventory/definition-request.v1.json",++ "visibility": "public",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.item.granted",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "events/payloads/inventory.item.granted.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.item.consumed",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "events/payloads/inventory.item.consumed.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.item.revoked",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "events/payloads/inventory.item.revoked.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.item.equipped",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "events/payloads/inventory.item.equipped.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.item.unequipped",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "events/payloads/inventory.item.unequipped.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"++ },++ {++ "id": "inventory.definition.published",++ "version": "1.0.0",++ "owner": "inventory",++ "schema": "events/payloads/inventory.definition.published.v1.json",++ "visibility": "first-party",++ "compatibility": "backward",++ "status": "active",++ "adr": "ADR-054"}]}nnew file mode 100644@@@ -0,0 +1,43 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.definition.published.v1.json",++ "title": "InventoryDefinitionPublishedPayload",++ "description": "inventory.definition.published v1 (OpenVibe.Inventory, ADR-054). A definition became grantable (a service's on request, a creator's after review). Envelope: subject { type: item_definition, id }, visibility public.",++ "type": "object",++ "required": [++ "definition_id",++ "kind",++ "name",++ "rarity",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200++ },++ "rarity": {++ "enum": [++ "common",++ "uncommon",++ "rare",++ "epic",++ "legendary"++ ]++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,32 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.consumed.v1.json",++ "title": "InventoryItemConsumedPayload",++ "description": "inventory.item.consumed v1 (OpenVibe.Inventory, ADR-054). An issuer consumed an instance (a one-use item used up). Envelope: subject { type: user, id: owner }, visibility subject.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "owner",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,37 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.equipped.v1.json",++ "title": "InventoryItemEquippedPayload",++ "description": "inventory.item.equipped v1 (OpenVibe.Inventory, ADR-054). A person equipped an instance in a slot; surfaces drop their cached equipped set. Envelope: subject { type: user, id: owner }, visibility public.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "kind",++ "slot",++ "owner"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "slot": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,45 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.granted.v1.json",++ "title": "InventoryItemGrantedPayload",++ "description": "inventory.item.granted v1 (OpenVibe.Inventory, ADR-054). An instance was granted or earned (ADR-054 §4). Envelope: subject { type: user, id: owner }, visibility subject, actor the issuer.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "kind",++ "owner",++ "origin",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "origin": {++ "enum": [++ "granted",++ "earned",++ "migrated"++ ]++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,33 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.revoked.v1.json",++ "title": "InventoryItemRevokedPayload",++ "description": "inventory.item.revoked v1 (OpenVibe.Inventory, ADR-054). An issuer or staff revoked an instance (granted in error, abuse). Envelope: subject { type: user, id: owner }, visibility subject.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "owner",++ "reason"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "reason": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200++ }++ }++}nnew file mode 100644@@@ -0,0 +1,27 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.unequipped.v1.json",++ "title": "InventoryItemUnequippedPayload",++ "description": "inventory.item.unequipped v1 (OpenVibe.Inventory, ADR-054). A person cleared a slot. Envelope: subject { type: user, id: owner }, visibility public.",++ "type": "object",++ "required": [++ "kind",++ "slot",++ "owner"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "slot": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,84 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/definition-request.v1.json",++ "title": "InventoryDefinitionRequest",++ "description": "Create or edit a definition in the issuer's namespace (inventory.definition.manage). A service's or app's definition is published when it asks; a creator's goes to staff review (in_review) first.",++ "type": "object",++ "required": [++ "kind",++ "name",++ "art",++ "rarity"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "description": {++ "type": "string",++ "maxLength": 500++ },++ "art": {++ "type": "object",++ "additionalProperties": false,++ "minProperties": 1,++ "properties": {++ "media_id": {++ "type": "string",++ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "An OpenVibe.Media object (an image, an animation)."++ },++ "token": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "description": "A token the kind's renderers know (a CSS class, a speech preset)."++ },++ "emoji": {++ "type": "string",++ "maxLength": 16++ }++ }++ },++ "rarity": {++ "enum": [++ "common",++ "uncommon",++ "rare",++ "epic",++ "legendary"++ ]++ },++ "attributes": {++ "type": "object"++ },++ "supply_cap": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 1++ },++ "aliases": {++ "type": "array",++ "maxItems": 8,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"++ }++ },++ "publish": {++ "type": "boolean",++ "description": "Ask for publication (a creator's definition goes to review)."++ }++ }++}nnew file mode 100644@@@ -0,0 +1,147 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/definition.v1.json",++ "title": "InventoryDefinition",++ "description": "An item definition (ADR-054 §2): one item of a kind, issued by a service, an app or a creator, with an honest rarity, attributes valid against the kind and an optional supply cap. Published definitions can be granted; retired ones cannot, and their instances stay.",++ "type": "object",++ "required": [++ "id",++ "kind",++ "name",++ "art",++ "rarity",++ "attributes",++ "issuer",++ "supply",++ "status",++ "created_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "description": {++ "type": "string",++ "maxLength": 500++ },++ "art": {++ "type": "object",++ "additionalProperties": false,++ "minProperties": 1,++ "properties": {++ "media_id": {++ "type": "string",++ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "An OpenVibe.Media object (an image, an animation)."++ },++ "token": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "description": "A token the kind's renderers know (a CSS class, a speech preset)."++ },++ "emoji": {++ "type": "string",++ "maxLength": 16++ }++ }++ },++ "rarity": {++ "enum": [++ "common",++ "uncommon",++ "rare",++ "epic",++ "legendary"++ ],++ "description": "Shown as is; any odds that apply are shown with it, never hidden."++ },++ "attributes": {++ "type": "object"++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ },++ "aliases": {++ "type": "array",++ "maxItems": 8,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"++ },++ "description": "Earlier ids of the same item (Live's fx_rainbow, hat_crown, …)."++ },++ "supply": {++ "type": "object",++ "required": [++ "cap",++ "issued"++ ],++ "additionalProperties": false,++ "properties": {++ "cap": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 1,++ "description": "null: unlimited."++ },++ "issued": {++ "type": "integer",++ "minimum": 0++ }++ }++ },++ "status": {++ "enum": [++ "draft",++ "in_review",++ "published",++ "retired"++ ]++ },++ "credit": {++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "name": {++ "type": "string",++ "maxLength": 80++ }++ },++ "description": "The creator of a community item (ADR-054 §6)."++ },++ "created_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ },++ "published_at": {++ "type": "string",++ "format": "date-time"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,31 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/equip-request.v1.json",++ "title": "InventoryEquipRequest",++ "description": "Equip an instance the person owns in one slot of its kind, or clear the slot (instance_id null). One item per slot; equipping replaces what was there.",++ "type": "object",++ "required": [++ "kind",++ "slot",++ "instance_id"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64++ },++ "slot": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "instance_id": {++ "type": [++ "string",++ "null"++ ],++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,20 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/equipped-batch.v1.json",++ "title": "InventoryEquippedBatch",++ "description": "The equipped sets of many people at once (GET /api/v1/equipped?subjects=…, up to 100): one query on the authority, one call per chat render batch.",++ "type": "object",++ "required": [++ "equipped"++ ],++ "additionalProperties": false,++ "properties": {++ "equipped": {++ "type": "array",++ "maxItems": 100,++ "items": {++ "$ref": "equipped.v1.json"++ }++ }++ }++}nnew file mode 100644@@@ -0,0 +1,53 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/equipped.v1.json",++ "title": "InventoryEquipped",++ "description": "What a person has equipped (ADR-054 §2), keyed <kind>:<slot>. Surfaces read it in batches (inventory.equipped-batch@1) and cache it briefly.",++ "type": "object",++ "required": [++ "subject",++ "slots",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "slots": {++ "type": "object",++ "propertyNames": {++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+:[a-z][a-z0-9_]{0,31}$"++ },++ "additionalProperties": {++ "type": "object",++ "required": [++ "instance_id",++ "definition_id"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "token": {++ "type": "string",++ "maxLength": 80,++ "description": "The definition's art token, so a renderer needs no second read."++ }++ }++ },++ "description": "<kind>:<slot> → the instance in use."++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,43 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/grant-request.v1.json",++ "title": "InventoryGrantRequest",++ "description": "An issuer grants one instance of a definition it issued to a person (inventory.item.grant). Idempotent per idempotency_key: a repeat answers the instance already granted. A capped definition that is sold out answers 409 inventory.supply_exhausted.",++ "type": "object",++ "required": [++ "definition_id",++ "subject",++ "idempotency_key"++ ],++ "additionalProperties": false,++ "properties": {++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "idempotency_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 128++ },++ "origin": {++ "enum": [++ "granted",++ "earned"++ ],++ "default": "granted"++ },++ "reason": {++ "type": "string",++ "maxLength": 200,++ "description": "Shown in the ledger: what the person did (a quest, an event, a milestone)."++ },++ "attributes": {++ "type": "object"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,59 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/instance.v1.json",++ "title": "InventoryInstance",++ "description": "One item a person owns (ADR-054 §2): a definition, its origin and state. bought and traded are reserved for the later money ADR (ADR-054 §5) and are refused until it is accepted.",++ "type": "object",++ "required": [++ "id",++ "definition_id",++ "owner",++ "origin",++ "state",++ "acquired_at"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "origin": {++ "enum": [++ "granted",++ "earned",++ "migrated",++ "bought",++ "traded"++ ]++ },++ "state": {++ "enum": [++ "owned",++ "consumed",++ "revoked"++ ]++ },++ "attributes": {++ "type": "object",++ "description": "Per-instance values (a serial number, a wear value), valid against the kind."++ },++ "serial": {++ "type": "integer",++ "minimum": 1,++ "description": "The instance's number within a capped supply."++ },++ "acquired_at": {++ "type": "string",++ "format": "date-time"++ }++ }++}nnew file mode 100644@@@ -0,0 +1,43 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/inventory.v1.json",++ "title": "InventoryList",++ "description": "A person's inventory page: their instances, newest first, with the definitions they refer to. The public read shows only owned instances of published definitions; the person's own read (inventory.item.list) also shows consumed and revoked ones.",++ "type": "object",++ "required": [++ "subject",++ "instances",++ "definitions",++ "next_cursor"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "instances": {++ "type": "array",++ "maxItems": 500,++ "items": {++ "$ref": "instance.v1.json"++ }++ },++ "definitions": {++ "type": "object",++ "propertyNames": {++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "additionalProperties": {++ "$ref": "definition.v1.json"++ }++ },++ "next_cursor": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 200++ }++ }++}nnew file mode 100644@@@ -0,0 +1,83 @@++{++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/kind.v1.json",++ "title": "InventoryKind",++ "description": "An item kind (ADR-054 §2): what items of the kind carry (an attribute schema), where they can be equipped (slots) and which surfaces render them. A new kind is a contract plus a renderer, never a new table.",++ "type": "object",++ "required": [++ "id",++ "name",++ "slots",++ "surfaces",++ "attributes",++ "stackable",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64,++ "description": "<namespace>.<kind>, e.g. live.name_effect, games.skin, network.badge."++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "description": {++ "type": "string",++ "maxLength": 500++ },++ "slots": {++ "type": "array",++ "maxItems": 16,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "description": "Where one item of the kind can be equipped; empty: the kind is not equippable (a collectible, a badge shown on the profile)."++ },++ "surfaces": {++ "type": "array",++ "minItems": 1,++ "maxItems": 16,++ "items": {++ "type": "object",++ "required": [++ "surface",++ "renderer"++ ],++ "additionalProperties": false,++ "properties": {++ "surface": {++ "type": "string",++ "pattern": "^(chat|overlay|profile|game:[a-z][a-z0-9-]*)$",++ "description": "Where an item of this kind shows."++ },++ "renderer": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "description": "The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1."++ }++ }++ }++ },++ "attributes": {++ "type": "object",++ "description": "A JSON Schema every definition's attributes must satisfy."++ },++ "stackable": {++ "type": "boolean",++ "description": "True: one person may hold several instances of one definition."++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$",++ "description": "Who owns the kind's namespace."++ }++ }++}nnew file mode 100644@@@ -0,0 +1,153 @@++# ADR-054: The OpenVibe inventory — one authority for items across the network++++**Status:** Accepted 2026-10-09 (plan track T21, step 1), on the owner's direction of 2026-10-08. Builds on ADR-012++(money lives only in Billing), ADR-025 (nothing traded between people without a new ADR), ADR-029 (account merge),++ADR-033 (account export and deletion), ADR-035 (each authority owns its PostgreSQL database) and ADR-048 (one authority++per resource).++++## Context++++> **Owner, 2026-10-08:** "improve and overhaul/remake the inventory system to be more like steam / csgo / etc style++> community driven and modular through sdk / api type shit rather than our current inventory seen on openvibe.live for++> name fx and particles and all that shit it should be a cross site network wide shared multi purpose modular system++> with user profiles and shit".++++What exists today is Live's cosmetics, and only Live can see them:++++- **The catalog is code.** `OpenVibe.Live` `server/monetization/cosmetics.js` `COSMETICS` lists name effects,++ particles, hats and voices, each with a tier and the CSS or speech values Live renders.++- **Ownership is two tables in Live's database.** `user_cosmetics` holds what a person unlocked (`user_id`, `item_id`,++ `category`) and `user_equipped` holds one item per slot. On 2026-10-09 production held 153 unlock rows for 8 people++ (voice 116, name effect 20, particle 10, hat 7) and 16 equipped slots; `user_equipped_tag` was empty.++- **Unlocks come only from Live's own routes** (`server/monetization/cosmetics-routes.js`). Nothing else can grant,++ show or equip an item, and nothing outside Live knows a person owns one.++++## Decision++++### 1. A new authority: OpenVibe.Inventory++++- **Identity:** service `inventory`, repository `OpenVibers/OpenVibe.Inventory`, loopback port 5030.++- **Storage:** its own PostgreSQL database `ov_inventory` (ADR-035).++- **Public read API:** `https://inventory.openvibe.network`, a Network subdomain like `api.` and `auth.`.++- **Owns:** item kinds, definitions, instances, the equipped set and the item ledger. Nothing else holds item++ ownership. Live keeps only the renderers for the kinds it shows.++- **Profile pages** stay with Network, which owns people: the public profile shows the person's showcase by reading++ Inventory.++++### 2. The model++++- **Kind** (a contract, string id `<namespace>.<kind>`, e.g. `live.name_effect`, `games.skin`, `network.badge`, `network.profile_frame`).++ A kind declares:++ - its attribute schema (JSON Schema);++ - its slots, so one item of the kind can be equipped per slot and surface;++ - the surfaces that render it (`chat`, `overlay`, `profile`, `game:<id>`), each with the renderer contract the++ surface implements.++++ A new kind is a contract plus a renderer, never a new table.++- **Definition** (`itd_<ULID>`): kind, name, description, art (a Media object or a renderer token such as a CSS class++ the kind's renderers know), rarity, attributes valid against the kind's schema, issuer, optional supply cap and++ status (`draft` → `in_review` → `published` → `retired`).++ - The issuer is a service, an app (ADR-014) or a creator.++ - Rarity is one of `common`, `uncommon`, `rare`, `epic`, `legendary`, shown with any odds that apply, never hidden.++- **Instance** (`inv_<ULID>`): one definition owned by one subject, with its origin (`granted`, `earned`, `migrated`;++ `bought` and `traded` are reserved for §5), acquisition time, optional per-instance attributes (a serial number, a++ wear value) and state (`owned`, `consumed`, `revoked`).++- **Equipped set:** per subject and slot, the instance in use. Surfaces read it in batches (many subjects in one call)++ and cache it briefly.++- **Ledger:** an append-only row for every movement (granted, earned, migrated, equipped, unequipped, consumed,++ revoked, merged), with the acting principal and the reason. This is the audit trail later trading needs.++++### 3. Who can do what (capabilities, guarded with `requireCapability`)++++| Capability | Who | What |++|---|---|---|++| `inventory.item.read` | public | a person's public inventory and equipped set, definitions, kinds |++| `inventory.item.list` | the person, or a service acting for them | their own full inventory, including hidden items |++| `inventory.equip.manage` | the person, or a service acting for them | equip and unequip their own instances |++| `inventory.item.grant` | an issuer, for definitions it issued | grant an instance to a subject (idempotent per key) |++| `inventory.item.consume` | an issuer, for definitions it issued | consume or revoke an instance |++| `inventory.definition.manage` | an issuer, for its namespace | create, edit, submit, retire definitions |++| `inventory.definition.review` | staff | publish or reject a submitted definition |++++Apps act with grants from Services (ADR-048). A grant to an app names the definition namespace it may issue in.++++### 4. Events++++The authority publishes these on OpenVibe.Events through its outbox:++++- `inventory.item.granted`++- `inventory.item.consumed`++- `inventory.item.revoked`++- `inventory.item.equipped`++- `inventory.item.unequipped`++- `inventory.definition.published`++++A person's own item events have visibility `subject`, and public profile changes are `public`.++++### 5. The money boundary++++ADR-012 and ADR-025 hold until a later ADR changes them.++++- **Not in v1:** items are not sold, bought, traded between people, cashed out or converted into OpenCoins or Vibes.++ There are no drops, cases or paid random rewards.++- **What a later ADR must cover first:** trading with escrow and confirmation, a marketplace priced in OpenCoins and++ Vibes, and a creator revenue share. It must give the legal basis per country, the Billing flows (ADR-012++ classification of every item that can be traded), trade holds, fraud and dispute handling, and minors' protection.++- **Allowed now:** issuers grant items for things people do (a quest, an event, a stream milestone, a game++ achievement), and staff grant them.++++### 6. Community items (the Workshop)++++- Creators submit definitions in their own namespace (`creator.<username>.*`).++- Review covers safety, art rights and honest rarity before anything is published.++- A published item credits its creator. A revenue share waits for §5's ADR.++++### 7. Account data and merge++++- **Export (ADR-033):** the person's instances, equipped set and ledger rows.++- **Deletion:** their instances and equipped set are deleted, and their ledger rows lose their subject, which keeps the++ supply counts true. A creator's published definitions stay, with the creator credit removed.++- **Merge (ADR-029):** instances move to the surviving subject, and duplicates of a unique definition keep the oldest.++++### 8. Live's cosmetics are the first kinds (convert, verify, delete)++++1. **Convert:**++ - Kinds `live.name_effect`, `live.particle`, `live.hat`, `live.voice` and `live.chat_tag` are registered.++ - Each `COSMETICS` entry becomes a definition issued by `live`, keeping its id as an alias. Tier maps to rarity:++ 1 common, 2 uncommon, 3 rare, 4 epic, 5 and 6 legendary.++ - Every `user_cosmetics` row becomes an instance with origin `migrated`, and every `user_equipped` row becomes the++ equipped slot.++2. **Verify:** each person's unlocked set and equipped slots match, row for row, on both sides.++3. **Switch:** Live reads through Inventory, behind a Live setting `INVENTORY_AUTHORITY` (`live` until the switch, then++ `inventory`). Its routes become calls to Inventory with Live's service token acting for the person.++4. **Delete:** after the N-1 window, a contract migration drops `user_cosmetics`, `user_equipped` and++ `user_equipped_tag`. Live keeps the CSS and speech renderers.++++## Alternatives considered++++- **Inside Network** (the wallet and profile area): rejected.++ - Network is identity and the money ledger, and an inventory has its own lifecycle, write load (grants from every++ game and site) and review queue.++ - Keeping it apart keeps the ADR-012 boundary visible: an item is never a balance.++- **Inside Live:** rejected, because items must work across every site.++- **Inside Games:** rejected, because Live, Chat, Community and the profile also show items, and Games is one issuer++ among many.++++## Rollback++++- **Before the Live switch:** stop the Inventory service; Live still reads its own tables.++- **After the switch and before the delete:** set `INVENTORY_AUTHORITY=live`. Live writes no item rows while switched,++ so anything granted in between is replayed from the Inventory ledger.++++## Acceptance tests++++- A kind's schema refuses a definition with invalid attributes, and a renderer is chosen per surface from the kind.++- A grant is idempotent per key, honours the supply cap, and writes one ledger row and one `inventory.item.granted`.++- An issuer cannot grant, consume or edit outside its namespace, and staff review is required to publish a creator's++ definition.++- Equip refuses an instance the person does not own or that is consumed, and holds one item per slot.++- A batch read of equipped sets for 100 subjects is one query.++- No route sells, buys, trades or converts an item (a route-inventory test, as for Trade).++- Live's migration verifies row for row before the switch; Live renders the same name effects, particles, hats and++ voices after it.++- Export, deletion and merge behave as in §7.@@@ -47,3 +47,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each| [ADR-046](ADR-046-universal-adaptive-fabric.md) | The universal adaptive fabric: offers, requirements, placement results and signed plans through one placer (`openvibe-sdk/placement`); health, cost, telemetry and usage samples; five trust classes, with `user-owned` eligible only when a workload names it; `worker:<class>` Node capabilities; the data plane keeps running on the last valid signed plan; T6 AI the reference consumer | Proposed 2026-10-03 (plan T1 step 3), for the owner's review || [ADR-048](ADR-048-services-control-plane.md) | The Services control plane: Services aggregates authorities and owns no other service's rows; every console action is a `common.resource-control-request@1` to the owning authority, answered with `common.resource-control-result@1` (idempotency keys, `confirmation_id` for sensitive actions); OVRN `ovrn:<service>:<project_id>:<type>/<id>` (`common.resource-name@1`) is the one cross-service resource name | Accepted 2026-10-04 (plan T13) || [ADR-053](ADR-053-website-host-boundary.md) | The Website/Host boundary: OpenVibe.Website owns authoring (projects, pages, revisions, builds, Media asset pointers and intended domains) and OpenVibe.Host owns site, deploy, activation, domain binding/verification/TLS and serving; Website keeps no duplicate `host_sites`/`host_deploys` rows and calls Host's routes; a Website build is not a Host deploy; Website composes Host + Codes + Actor + Run + Media and is not OpenVibe.Sites | Proposed 2026-10-05 (plan T19), for the owner's review |++| [ADR-054](ADR-054-inventory-authority.md) | The OpenVibe inventory: a new authority, OpenVibe.Inventory (`inventory`, `ov_inventory`), owns item kinds (contract + renderer per surface), definitions (`itd_`), instances (`inv_`), the equipped set and an append-only ledger; issuers grant within their namespace; no selling, buying, trading or conversion until a later money ADR (ADR-012/ADR-025); Live's cosmetics are the first kinds, migrated convert-verify-delete | Accepted 2026-10-09 (plan T21) |nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "kind": "network.profile_frame",++ "name": "x",++ "rarity": "rare"++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "kind": "network.profile_frame",++ "name": "Aurora frame",++ "art": {++ "media_id": "med_01JZ0000000000000000000MED"++ },++ "rarity": "rare",++ "supply_cap": 500,++ "publish": true++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "kind": "network.profile_frame",++ "name": "Aurora frame",++ "rarity": "rare",++ "issuer": "user:usr_01JZ0000000000000000000AAA"++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "definition_id": "itd_01JZ00000000000000000001T2",++ "kind": "network.profile_frame",++ "name": "Aurora frame",++ "rarity": "rare",++ "issuer": "user:usr_01JZ0000000000000000000AAA"++}nnew file mode 100644@@@ -0,0 +1,26 @@++{++ "id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "name": "Rainbow Name",++ "description": "Rainbow cycling colors",++ "art": {++ "token": "name-fx-rainbow",++ "emoji": "🌈"++ },++ "rarity": "common",++ "attributes": {++ "css_class": "name-fx-rainbow"++ },++ "issuer": "live",++ "aliases": [++ "fx_rainbow"++ ],++ "supply": {++ "cap": null,++ "issued": 4++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,26 @@++{++ "id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "name": "Rainbow Name",++ "description": "Rainbow cycling colors",++ "art": {++ "token": "name-fx-rainbow",++ "emoji": "🌈"++ },++ "rarity": "mythic",++ "attributes": {++ "css_class": "name-fx-rainbow"++ },++ "issuer": "service:live",++ "aliases": [++ "fx_rainbow"++ ],++ "supply": {++ "cap": null,++ "issued": 4++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,23 @@++{++ "id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "name": "Rainbow Name",++ "description": "Rainbow cycling colors",++ "art": {},++ "rarity": "common",++ "attributes": {++ "css_class": "name-fx-rainbow"++ },++ "issuer": "service:live",++ "aliases": [++ "fx_rainbow"++ ],++ "supply": {++ "cap": null,++ "issued": 4++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,25 @@++{++ "id": "itd_01JZ00000000000000000001T2",++ "kind": "network.profile_frame",++ "name": "Aurora frame",++ "description": "Rainbow cycling colors",++ "art": {++ "media_id": "med_01JZ0000000000000000000MED"++ },++ "rarity": "rare",++ "attributes": {},++ "issuer": "user:usr_01JZ0000000000000000000AAA",++ "aliases": [],++ "supply": {++ "cap": 500,++ "issued": 12++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z",++ "credit": {++ "subject": "usr_01JZ0000000000000000000AAA",++ "name": "aurora_artist"++ }++}nnew file mode 100644@@@ -0,0 +1,26 @@++{++ "id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "name": "Rainbow Name",++ "description": "Rainbow cycling colors",++ "art": {++ "token": "name-fx-rainbow",++ "emoji": "🌈"++ },++ "rarity": "common",++ "attributes": {++ "css_class": "name-fx-rainbow"++ },++ "issuer": "service:live",++ "aliases": [++ "fx_rainbow"++ ],++ "supply": {++ "cap": null,++ "issued": 4++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "kind": "live.hat",++ "instance_id": "inv_01JZ00000000000000000001NV"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "kind": "live.hat",++ "slot": "hat",++ "instance_id": null++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "kind": "live.name_effect",++ "slot": "name_effect",++ "instance_id": "inv_01JZ00000000000000000001NV"++}nnew file mode 100644@@@ -0,0 +1,13 @@++{++ "equipped": {++ "subject": "usr_01JZ0000000000000000000AAA",++ "slots": {++ "live.name_effect:name_effect": {++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "token": "name-fx-rainbow"++ }++ },++ "updated_at": "2026-10-09T03:00:00Z"++ }++}nnew file mode 100644@@@ -0,0 +1,20 @@++{++ "equipped": [++ {++ "subject": "usr_01JZ0000000000000000000AAA",++ "slots": {++ "live.name_effect:name_effect": {++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "token": "name-fx-rainbow"++ }++ },++ "updated_at": "2026-10-09T03:00:00Z"++ },++ {++ "subject": "usr_01JZ0000000000000000000BBB",++ "slots": {},++ "updated_at": "2026-10-09T03:00:00Z"++ }++ ]++}nnew file mode 100644@@@ -0,0 +1,10 @@++{++ "subject": "usr_01JZ0000000000000000000AAA",++ "slots": {++ "name_effect": {++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD"++ }++ },++ "updated_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "subject": "usr_01JZ0000000000000000000BBB",++ "slots": {},++ "updated_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,11 @@++{++ "subject": "usr_01JZ0000000000000000000AAA",++ "slots": {++ "live.name_effect:name_effect": {++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "token": "name-fx-rainbow"++ }++ },++ "updated_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "subject": "usr_01JZ0000000000000000000AAA",++ "idempotency_key": "k-12345678",++ "origin": "bought"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "subject": "usr_01JZ0000000000000000000AAA",++ "idempotency_key": "k"++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "subject": "usr_01JZ0000000000000000000AAA",++ "idempotency_key": "quest-0000-0001",++ "origin": "earned",++ "reason": "Completed the first-stream quest"++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "gst_01JZ0000000000000000000AAA",++ "origin": "migrated",++ "state": "owned",++ "acquired_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "origin": "migrated",++ "state": "sold",++ "acquired_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "origin": "migrated",++ "state": "owned",++ "acquired_at": "2026-10-09T03:00:00Z"++}nnew file mode 100644@@@ -0,0 +1,12 @@++{++ "id": "inv_01JZ00000000000000000001N2",++ "definition_id": "itd_01JZ00000000000000000001T2",++ "owner": "usr_01JZ0000000000000000000AAA",++ "origin": "earned",++ "state": "owned",++ "acquired_at": "2026-10-09T03:00:00Z",++ "serial": 12,++ "attributes": {++ "wear": 0.1++ }++}nnew file mode 100644@@@ -0,0 +1,33 @@++{++ "subject": "usr_01JZ0000000000000000000AAA",++ "instances": [],++ "definitions": {++ "fx_rainbow": {++ "id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "name": "Rainbow Name",++ "description": "Rainbow cycling colors",++ "art": {++ "token": "name-fx-rainbow",++ "emoji": "🌈"++ },++ "rarity": "common",++ "attributes": {++ "css_class": "name-fx-rainbow"++ },++ "issuer": "service:live",++ "aliases": [++ "fx_rainbow"++ ],++ "supply": {++ "cap": null,++ "issued": 4++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z"++ }++ },++ "next_cursor": null++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "subject": "usr_01JZ0000000000000000000AAA",++ "instances": [],++ "definitions": {}++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "subject": "usr_01JZ0000000000000000000BBB",++ "instances": [],++ "definitions": {},++ "next_cursor": null++}nnew file mode 100644@@@ -0,0 +1,42 @@++{++ "subject": "usr_01JZ0000000000000000000AAA",++ "instances": [++ {++ "id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "origin": "migrated",++ "state": "owned",++ "acquired_at": "2026-10-09T03:00:00Z"++ }++ ],++ "definitions": {++ "itd_01JZ00000000000000000001TD": {++ "id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "name": "Rainbow Name",++ "description": "Rainbow cycling colors",++ "art": {++ "token": "name-fx-rainbow",++ "emoji": "🌈"++ },++ "rarity": "common",++ "attributes": {++ "css_class": "name-fx-rainbow"++ },++ "issuer": "service:live",++ "aliases": [++ "fx_rainbow"++ ],++ "supply": {++ "cap": null,++ "issued": 4++ },++ "status": "published",++ "created_at": "2026-10-09T03:00:00Z",++ "updated_at": "2026-10-09T03:00:00Z",++ "published_at": "2026-10-09T03:00:00Z"++ }++ },++ "next_cursor": null++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "issuer": "service:games"++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "issuer": "service:games"++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "slot": "name_effect",++ "owner": "usr_01JZ0000000000000000000AAA"++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "slot": "name_effect",++ "owner": "usr_01JZ0000000000000000000AAA"++}nnew file mode 100644@@@ -0,0 +1,7 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "owner": "usr_01JZ0000000000000000000AAA",++ "origin": "earned",++ "issuer": "service:quest"++}nnew file mode 100644@@@ -0,0 +1,8 @@++{++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "kind": "live.name_effect",++ "owner": "usr_01JZ0000000000000000000AAA",++ "origin": "earned",++ "issuer": "service:quest"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "reason": "granted twice by mistake"++}nnew file mode 100644@@@ -0,0 +1,6 @@++{++ "instance_id": "inv_01JZ00000000000000000001NV",++ "definition_id": "itd_01JZ00000000000000000001TD",++ "owner": "usr_01JZ0000000000000000000AAA",++ "reason": "granted twice by mistake"++}nnew file mode 100644@@@ -0,0 +1,4 @@++{++ "slot": "hat",++ "owner": "usr_01JZ0000000000000000000AAA"++}nnew file mode 100644@@@ -0,0 +1,5 @@++{++ "kind": "live.hat",++ "slot": "hat",++ "owner": "usr_01JZ0000000000000000000AAA"++}nnew file mode 100644@@@ -0,0 +1,31 @@++{++ "id": "NameEffect",++ "name": "Name effect",++ "description": "How your name looks in chat.",++ "slots": [++ "name_effect"++ ],++ "surfaces": [++ {++ "surface": "chat",++ "renderer": "live.name_effect.css@1"++ },++ {++ "surface": "profile",++ "renderer": "live.name_effect.css@1"++ }++ ],++ "attributes": {++ "type": "object",++ "required": [++ "css_class"++ ],++ "properties": {++ "css_class": {++ "type": "string"++ }++ }++ },++ "stackable": false,++ "issuer": "service:live"++}nnew file mode 100644@@@ -0,0 +1,27 @@++{++ "id": "live.name_effect",++ "name": "Name effect",++ "description": "How your name looks in chat.",++ "slots": [++ "name_effect"++ ],++ "surfaces": [++ {++ "surface": "billboard",++ "renderer": "x"++ }++ ],++ "attributes": {++ "type": "object",++ "required": [++ "css_class"++ ],++ "properties": {++ "css_class": {++ "type": "string"++ }++ }++ },++ "stackable": false,++ "issuer": "service:live"++}nnew file mode 100644@@@ -0,0 +1,22 @@++{++ "id": "live.name_effect",++ "name": "Name effect",++ "description": "How your name looks in chat.",++ "slots": [++ "name_effect"++ ],++ "surfaces": [],++ "attributes": {++ "type": "object",++ "required": [++ "css_class"++ ],++ "properties": {++ "css_class": {++ "type": "string"++ }++ }++ },++ "stackable": false,++ "issuer": "service:live"++}nnew file mode 100644@@@ -0,0 +1,25 @@++{++ "id": "network.badge",++ "name": "Badge",++ "description": "How your name looks in chat.",++ "slots": [],++ "surfaces": [++ {++ "surface": "profile",++ "renderer": "network.badge.img@1"++ }++ ],++ "attributes": {++ "type": "object",++ "required": [++ "css_class"++ ],++ "properties": {++ "css_class": {++ "type": "string"++ }++ }++ },++ "stackable": true,++ "issuer": "service:network"++}nnew file mode 100644@@@ -0,0 +1,31 @@++{++ "id": "live.name_effect",++ "name": "Name effect",++ "description": "How your name looks in chat.",++ "slots": [++ "name_effect"++ ],++ "surfaces": [++ {++ "surface": "chat",++ "renderer": "live.name_effect.css@1"++ },++ {++ "surface": "profile",++ "renderer": "live.name_effect.css@1"++ }++ ],++ "attributes": {++ "type": "object",++ "required": [++ "css_class"++ ],++ "properties": {++ "css_class": {++ "type": "string"++ }++ }++ },++ "stackable": false,++ "issuer": "service:live"++}@@@ -73814,6 +73814,861 @@}]}++ },++ "inventory.kind": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/kind.v1.json",++ "title": "InventoryKind",++ "description": "An item kind (ADR-054 §2): what items of the kind carry (an attribute schema), where they can be equipped (slots) and which surfaces render them. A new kind is a contract plus a renderer, never a new table.",++ "type": "object",++ "required": [++ "id",++ "name",++ "slots",++ "surfaces",++ "attributes",++ "stackable",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64,++ "description": "<namespace>.<kind>, e.g. live.name_effect, games.skin, network.badge."++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "description": {++ "type": "string",++ "maxLength": 500++ },++ "slots": {++ "type": "array",++ "maxItems": 16,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "description": "Where one item of the kind can be equipped; empty: the kind is not equippable (a collectible, a badge shown on the profile)."++ },++ "surfaces": {++ "type": "array",++ "minItems": 1,++ "maxItems": 16,++ "items": {++ "type": "object",++ "required": [++ "surface",++ "renderer"++ ],++ "additionalProperties": false,++ "properties": {++ "surface": {++ "type": "string",++ "pattern": "^(chat|overlay|profile|game:[a-z][a-z0-9-]*)$",++ "description": "Where an item of this kind shows."++ },++ "renderer": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "description": "The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1."++ }++ }++ }++ },++ "attributes": {++ "type": "object",++ "description": "A JSON Schema every definition's attributes must satisfy."++ },++ "stackable": {++ "type": "boolean",++ "description": "True: one person may hold several instances of one definition."++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$",++ "description": "Who owns the kind's namespace."++ }++ }++ }++ },++ "inventory.definition": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/definition.v1.json",++ "title": "InventoryDefinition",++ "description": "An item definition (ADR-054 §2): one item of a kind, issued by a service, an app or a creator, with an honest rarity, attributes valid against the kind and an optional supply cap. Published definitions can be granted; retired ones cannot, and their instances stay.",++ "type": "object",++ "required": [++ "id",++ "kind",++ "name",++ "art",++ "rarity",++ "attributes",++ "issuer",++ "supply",++ "status",++ "created_at",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "description": {++ "type": "string",++ "maxLength": 500++ },++ "art": {++ "type": "object",++ "additionalProperties": false,++ "minProperties": 1,++ "properties": {++ "media_id": {++ "type": "string",++ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "An OpenVibe.Media object (an image, an animation)."++ },++ "token": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "description": "A token the kind's renderers know (a CSS class, a speech preset)."++ },++ "emoji": {++ "type": "string",++ "maxLength": 16++ }++ }++ },++ "rarity": {++ "enum": [++ "common",++ "uncommon",++ "rare",++ "epic",++ "legendary"++ ],++ "description": "Shown as is; any odds that apply are shown with it, never hidden."++ },++ "attributes": {++ "type": "object"++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ },++ "aliases": {++ "type": "array",++ "maxItems": 8,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"++ },++ "description": "Earlier ids of the same item (Live's fx_rainbow, hat_crown, …)."++ },++ "supply": {++ "type": "object",++ "required": [++ "cap",++ "issued"++ ],++ "additionalProperties": false,++ "properties": {++ "cap": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 1,++ "description": "null: unlimited."++ },++ "issued": {++ "type": "integer",++ "minimum": 0++ }++ }++ },++ "status": {++ "enum": [++ "draft",++ "in_review",++ "published",++ "retired"++ ]++ },++ "credit": {++ "type": "object",++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "name": {++ "type": "string",++ "maxLength": 80++ }++ },++ "description": "The creator of a community item (ADR-054 §6)."++ },++ "created_at": {++ "type": "string",++ "format": "date-time"++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ },++ "published_at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ },++ "inventory.instance": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/instance.v1.json",++ "title": "InventoryInstance",++ "description": "One item a person owns (ADR-054 §2): a definition, its origin and state. bought and traded are reserved for the later money ADR (ADR-054 §5) and are refused until it is accepted.",++ "type": "object",++ "required": [++ "id",++ "definition_id",++ "owner",++ "origin",++ "state",++ "acquired_at"++ ],++ "additionalProperties": false,++ "properties": {++ "id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "origin": {++ "enum": [++ "granted",++ "earned",++ "migrated",++ "bought",++ "traded"++ ]++ },++ "state": {++ "enum": [++ "owned",++ "consumed",++ "revoked"++ ]++ },++ "attributes": {++ "type": "object",++ "description": "Per-instance values (a serial number, a wear value), valid against the kind."++ },++ "serial": {++ "type": "integer",++ "minimum": 1,++ "description": "The instance's number within a capped supply."++ },++ "acquired_at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ },++ "inventory.inventory": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/inventory.v1.json",++ "title": "InventoryList",++ "description": "A person's inventory page: their instances, newest first, with the definitions they refer to. The public read shows only owned instances of published definitions; the person's own read (inventory.item.list) also shows consumed and revoked ones.",++ "type": "object",++ "required": [++ "subject",++ "instances",++ "definitions",++ "next_cursor"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "instances": {++ "type": "array",++ "maxItems": 500,++ "items": {++ "$ref": "instance.v1.json"++ }++ },++ "definitions": {++ "type": "object",++ "propertyNames": {++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "additionalProperties": {++ "$ref": "definition.v1.json"++ }++ },++ "next_cursor": {++ "type": [++ "string",++ "null"++ ],++ "maxLength": 200++ }++ }++ }++ },++ "inventory.equipped": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/equipped.v1.json",++ "title": "InventoryEquipped",++ "description": "What a person has equipped (ADR-054 §2), keyed <kind>:<slot>. Surfaces read it in batches (inventory.equipped-batch@1) and cache it briefly.",++ "type": "object",++ "required": [++ "subject",++ "slots",++ "updated_at"++ ],++ "additionalProperties": false,++ "properties": {++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "slots": {++ "type": "object",++ "propertyNames": {++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+:[a-z][a-z0-9_]{0,31}$"++ },++ "additionalProperties": {++ "type": "object",++ "required": [++ "instance_id",++ "definition_id"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "token": {++ "type": "string",++ "maxLength": 80,++ "description": "The definition's art token, so a renderer needs no second read."++ }++ }++ },++ "description": "<kind>:<slot> → the instance in use."++ },++ "updated_at": {++ "type": "string",++ "format": "date-time"++ }++ }++ }++ },++ "inventory.equipped-batch": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/equipped-batch.v1.json",++ "title": "InventoryEquippedBatch",++ "description": "The equipped sets of many people at once (GET /api/v1/equipped?subjects=…, up to 100): one query on the authority, one call per chat render batch.",++ "type": "object",++ "required": [++ "equipped"++ ],++ "additionalProperties": false,++ "properties": {++ "equipped": {++ "type": "array",++ "maxItems": 100,++ "items": {++ "$ref": "equipped.v1.json"++ }++ }++ }++ }++ },++ "inventory.grant-request": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/grant-request.v1.json",++ "title": "InventoryGrantRequest",++ "description": "An issuer grants one instance of a definition it issued to a person (inventory.item.grant). Idempotent per idempotency_key: a repeat answers the instance already granted. A capped definition that is sold out answers 409 inventory.supply_exhausted.",++ "type": "object",++ "required": [++ "definition_id",++ "subject",++ "idempotency_key"++ ],++ "additionalProperties": false,++ "properties": {++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "subject": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "idempotency_key": {++ "type": "string",++ "minLength": 8,++ "maxLength": 128++ },++ "origin": {++ "enum": [++ "granted",++ "earned"++ ],++ "default": "granted"++ },++ "reason": {++ "type": "string",++ "maxLength": 200,++ "description": "Shown in the ledger: what the person did (a quest, an event, a milestone)."++ },++ "attributes": {++ "type": "object"++ }++ }++ }++ },++ "inventory.equip-request": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/equip-request.v1.json",++ "title": "InventoryEquipRequest",++ "description": "Equip an instance the person owns in one slot of its kind, or clear the slot (instance_id null). One item per slot; equipping replaces what was there.",++ "type": "object",++ "required": [++ "kind",++ "slot",++ "instance_id"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64++ },++ "slot": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "instance_id": {++ "type": [++ "string",++ "null"++ ],++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++ }++ },++ "inventory.definition-request": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/inventory/definition-request.v1.json",++ "title": "InventoryDefinitionRequest",++ "description": "Create or edit a definition in the issuer's namespace (inventory.definition.manage). A service's or app's definition is published when it asks; a creator's goes to staff review (in_review) first.",++ "type": "object",++ "required": [++ "kind",++ "name",++ "art",++ "rarity"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",++ "maxLength": 64++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80++ },++ "description": {++ "type": "string",++ "maxLength": 500++ },++ "art": {++ "type": "object",++ "additionalProperties": false,++ "minProperties": 1,++ "properties": {++ "media_id": {++ "type": "string",++ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",++ "description": "An OpenVibe.Media object (an image, an animation)."++ },++ "token": {++ "type": "string",++ "minLength": 1,++ "maxLength": 80,++ "description": "A token the kind's renderers know (a CSS class, a speech preset)."++ },++ "emoji": {++ "type": "string",++ "maxLength": 16++ }++ }++ },++ "rarity": {++ "enum": [++ "common",++ "uncommon",++ "rare",++ "epic",++ "legendary"++ ]++ },++ "attributes": {++ "type": "object"++ },++ "supply_cap": {++ "type": [++ "integer",++ "null"++ ],++ "minimum": 1++ },++ "aliases": {++ "type": "array",++ "maxItems": 8,++ "uniqueItems": true,++ "items": {++ "type": "string",++ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"++ }++ },++ "publish": {++ "type": "boolean",++ "description": "Ask for publication (a creator's definition goes to review)."++ }++ }++ }++ },++ "inventory.item.granted": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.granted.v1.json",++ "title": "InventoryItemGrantedPayload",++ "description": "inventory.item.granted v1 (OpenVibe.Inventory, ADR-054). An instance was granted or earned (ADR-054 §4). Envelope: subject { type: user, id: owner }, visibility subject, actor the issuer.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "kind",++ "owner",++ "origin",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "origin": {++ "enum": [++ "granted",++ "earned",++ "migrated"++ ]++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ }++ }++ }++ },++ "inventory.item.consumed": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.consumed.v1.json",++ "title": "InventoryItemConsumedPayload",++ "description": "inventory.item.consumed v1 (OpenVibe.Inventory, ADR-054). An issuer consumed an instance (a one-use item used up). Envelope: subject { type: user, id: owner }, visibility subject.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "owner",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ }++ }++ }++ },++ "inventory.item.revoked": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.revoked.v1.json",++ "title": "InventoryItemRevokedPayload",++ "description": "inventory.item.revoked v1 (OpenVibe.Inventory, ADR-054). An issuer or staff revoked an instance (granted in error, abuse). Envelope: subject { type: user, id: owner }, visibility subject.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "owner",++ "reason"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "reason": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200++ }++ }++ }++ },++ "inventory.item.equipped": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.equipped.v1.json",++ "title": "InventoryItemEquippedPayload",++ "description": "inventory.item.equipped v1 (OpenVibe.Inventory, ADR-054). A person equipped an instance in a slot; surfaces drop their cached equipped set. Envelope: subject { type: user, id: owner }, visibility public.",++ "type": "object",++ "required": [++ "instance_id",++ "definition_id",++ "kind",++ "slot",++ "owner"++ ],++ "additionalProperties": false,++ "properties": {++ "instance_id": {++ "type": "string",++ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "slot": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++ }++ },++ "inventory.item.unequipped": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.unequipped.v1.json",++ "title": "InventoryItemUnequippedPayload",++ "description": "inventory.item.unequipped v1 (OpenVibe.Inventory, ADR-054). A person cleared a slot. Envelope: subject { type: user, id: owner }, visibility public.",++ "type": "object",++ "required": [++ "kind",++ "slot",++ "owner"++ ],++ "additionalProperties": false,++ "properties": {++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "slot": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]{0,31}$"++ },++ "owner": {++ "type": "string",++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"++ }++ }++ }++ },++ "inventory.definition.published": {++ "version": "1.0.0",++ "owner": "inventory",++ "status": "active",++ "schema": {++ "$schema": "https://json-schema.org/draft/2020-12/schema",++ "$id": "https://openvibe.network/contracts/events/payloads/inventory.definition.published.v1.json",++ "title": "InventoryDefinitionPublishedPayload",++ "description": "inventory.definition.published v1 (OpenVibe.Inventory, ADR-054). A definition became grantable (a service's on request, a creator's after review). Envelope: subject { type: item_definition, id }, visibility public.",++ "type": "object",++ "required": [++ "definition_id",++ "kind",++ "name",++ "rarity",++ "issuer"++ ],++ "additionalProperties": false,++ "properties": {++ "definition_id": {++ "type": "string",++ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"++ },++ "kind": {++ "type": "string",++ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"++ },++ "name": {++ "type": "string",++ "minLength": 1,++ "maxLength": 200++ },++ "rarity": {++ "enum": [++ "common",++ "uncommon",++ "rare",++ "epic",++ "legendary"++ ]++ },++ "issuer": {++ "type": "string",++ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"++ }++ }++ }}}}@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Actor API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.AI API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Billing API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Blog API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Bot API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Chat API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Community API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Coupons API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Deals API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Events API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Food API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Games API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Host API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Live API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Media API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Network API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.News API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenRe.Stream API",-- "version": "0.120.0",-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Reviews API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Run API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Search API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Services API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Sources API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tips API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Tools API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Trade API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.VIP API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Watch API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.","license": {"name": "MIT","identifier": "MIT"@@@ -3,8 +3,8 @@"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema","info": {"title": "OpenVibe.Wiki API",-- "version": "0.120.0",-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for 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"@@@ -59044,3 +59044,1750 @@ export type FoodPlanResult =plans: FoodPlan[];}| FoodPlan;++++/** [email protected] (owner: inventory) */++/**++ * An item kind (ADR-054 §2): what items of the kind carry (an attribute schema), where they can be equipped (slots) and which surfaces render them. A new kind is a contract plus a renderer, never a new table.++ */++export interface InventoryKind {++ /**++ * <namespace>.<kind>, e.g. live.name_effect, games.skin, network.badge.++ */++ id: string;++ name: string;++ description?: string;++ /**++ * Where one item of the kind can be equipped; empty: the kind is not equippable (a collectible, a badge shown on the profile).++ *++ * @maxItems 16++ */++ slots:++ | []++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ]++ | [++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string,++ string++ ];++ /**++ * @minItems 1++ * @maxItems 16++ */++ surfaces:++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ]++ | [++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ },++ {++ /**++ * Where an item of this kind shows.++ */++ surface: string;++ /**++ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.++ */++ renderer: string;++ }++ ];++ /**++ * A JSON Schema every definition's attributes must satisfy.++ */++ attributes: {};++ /**++ * True: one person may hold several instances of one definition.++ */++ stackable: boolean;++ /**++ * Who owns the kind's namespace.++ */++ issuer: string;++}++++/** [email protected] (owner: inventory) */++/**++ * An item definition (ADR-054 §2): one item of a kind, issued by a service, an app or a creator, with an honest rarity, attributes valid against the kind and an optional supply cap. Published definitions can be granted; retired ones cannot, and their instances stay.++ */++export interface InventoryDefinition {++ id: string;++ kind: string;++ name: string;++ description?: string;++ art: {++ /**++ * An OpenVibe.Media object (an image, an animation).++ */++ media_id?: string;++ /**++ * A token the kind's renderers know (a CSS class, a speech preset).++ */++ token?: string;++ emoji?: string;++ };++ /**++ * Shown as is; any odds that apply are shown with it, never hidden.++ */++ rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";++ attributes: {};++ issuer: string;++ /**++ * Earlier ids of the same item (Live's fx_rainbow, hat_crown, …).++ *++ * @maxItems 8++ */++ aliases?:++ | []++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string];++ supply: {++ /**++ * null: unlimited.++ */++ cap: number | null;++ issued: number;++ };++ status: "draft" | "in_review" | "published" | "retired";++ /**++ * The creator of a community item (ADR-054 §6).++ */++ credit?: {++ subject?: string;++ name?: string;++ };++ created_at: string;++ updated_at: string;++ published_at?: string;++}++++/** [email protected] (owner: inventory) */++/**++ * One item a person owns (ADR-054 §2): a definition, its origin and state. bought and traded are reserved for the later money ADR (ADR-054 §5) and are refused until it is accepted.++ */++export interface InventoryInstance {++ id: string;++ definition_id: string;++ owner: string;++ origin: "granted" | "earned" | "migrated" | "bought" | "traded";++ state: "owned" | "consumed" | "revoked";++ /**++ * Per-instance values (a serial number, a wear value), valid against the kind.++ */++ attributes?: {};++ /**++ * The instance's number within a capped supply.++ */++ serial?: number;++ acquired_at: string;++}++++/** [email protected] (owner: inventory) */++/**++ * A person's inventory page: their instances, newest first, with the definitions they refer to. The public read shows only owned instances of published definitions; the person's own read (inventory.item.list) also shows consumed and revoked ones.++ */++export interface InventoryList {++ subject: string;++ /**++ * @maxItems 500++ */++ instances: InventoryInstance[];++ definitions: {++ [k: string]: InventoryDefinition | undefined;++ };++ next_cursor: string | null;++}++++/** [email protected] (owner: inventory) */++/**++ * What a person has equipped (ADR-054 §2), keyed <kind>:<slot>. Surfaces read it in batches (inventory.equipped-batch@1) and cache it briefly.++ */++export interface InventoryEquipped {++ subject: string;++ /**++ * <kind>:<slot> → the instance in use.++ */++ slots: {++ [k: string]:++ | {++ instance_id: string;++ definition_id: string;++ /**++ * The definition's art token, so a renderer needs no second read.++ */++ token?: string;++ }++ | undefined;++ };++ updated_at: string;++}++++/** [email protected] (owner: inventory) */++/**++ * The equipped sets of many people at once (GET /api/v1/equipped?subjects=…, up to 100): one query on the authority, one call per chat render batch.++ */++export interface InventoryEquippedBatch {++ /**++ * @maxItems 100++ */++ equipped: InventoryEquipped[];++}++++/** [email protected] (owner: inventory) */++/**++ * An issuer grants one instance of a definition it issued to a person (inventory.item.grant). Idempotent per idempotency_key: a repeat answers the instance already granted. A capped definition that is sold out answers 409 inventory.supply_exhausted.++ */++export interface InventoryGrantRequest {++ definition_id: string;++ subject: string;++ idempotency_key: string;++ origin?: "granted" | "earned";++ /**++ * Shown in the ledger: what the person did (a quest, an event, a milestone).++ */++ reason?: string;++ attributes?: {};++}++++/** [email protected] (owner: inventory) */++/**++ * Equip an instance the person owns in one slot of its kind, or clear the slot (instance_id null). One item per slot; equipping replaces what was there.++ */++export interface InventoryEquipRequest {++ kind: string;++ slot: string;++ instance_id: string | null;++}++++/** [email protected] (owner: inventory) */++/**++ * Create or edit a definition in the issuer's namespace (inventory.definition.manage). A service's or app's definition is published when it asks; a creator's goes to staff review (in_review) first.++ */++export interface InventoryDefinitionRequest {++ kind: string;++ name: string;++ description?: string;++ art: {++ /**++ * An OpenVibe.Media object (an image, an animation).++ */++ media_id?: string;++ /**++ * A token the kind's renderers know (a CSS class, a speech preset).++ */++ token?: string;++ emoji?: string;++ };++ rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";++ attributes?: {};++ supply_cap?: number | null;++ /**++ * @maxItems 8++ */++ aliases?:++ | []++ | [string]++ | [string, string]++ | [string, string, string]++ | [string, string, string, string]++ | [string, string, string, string, string]++ | [string, string, string, string, string, string]++ | [string, string, string, string, string, string, string]++ | [string, string, string, string, string, string, string, string];++ /**++ * Ask for publication (a creator's definition goes to review).++ */++ publish?: boolean;++}++++/** [email protected] (owner: inventory) */++/**++ * inventory.item.granted v1 (OpenVibe.Inventory, ADR-054). An instance was granted or earned (ADR-054 §4). Envelope: subject { type: user, id: owner }, visibility subject, actor the issuer.++ */++export interface InventoryItemGrantedPayload {++ instance_id: string;++ definition_id: string;++ kind: string;++ owner: string;++ origin: "granted" | "earned" | "migrated";++ issuer: string;++}++++/** [email protected] (owner: inventory) */++/**++ * inventory.item.consumed v1 (OpenVibe.Inventory, ADR-054). An issuer consumed an instance (a one-use item used up). Envelope: subject { type: user, id: owner }, visibility subject.++ */++export interface InventoryItemConsumedPayload {++ instance_id: string;++ definition_id: string;++ owner: string;++ issuer: string;++}++++/** [email protected] (owner: inventory) */++/**++ * inventory.item.revoked v1 (OpenVibe.Inventory, ADR-054). An issuer or staff revoked an instance (granted in error, abuse). Envelope: subject { type: user, id: owner }, visibility subject.++ */++export interface InventoryItemRevokedPayload {++ instance_id: string;++ definition_id: string;++ owner: string;++ reason: string;++}++++/** [email protected] (owner: inventory) */++/**++ * inventory.item.equipped v1 (OpenVibe.Inventory, ADR-054). A person equipped an instance in a slot; surfaces drop their cached equipped set. Envelope: subject { type: user, id: owner }, visibility public.++ */++export interface InventoryItemEquippedPayload {++ instance_id: string;++ definition_id: string;++ kind: string;++ slot: string;++ owner: string;++}++++/** [email protected] (owner: inventory) */++/**++ * inventory.item.unequipped v1 (OpenVibe.Inventory, ADR-054). A person cleared a slot. Envelope: subject { type: user, id: owner }, visibility public.++ */++export interface InventoryItemUnequippedPayload {++ kind: string;++ slot: string;++ owner: string;++}++++/** [email protected] (owner: inventory) */++/**++ * inventory.definition.published v1 (OpenVibe.Inventory, ADR-054). A definition became grantable (a service's on request, a creator's after review). Envelope: subject { type: item_definition, id }, visibility public.++ */++export interface InventoryDefinitionPublishedPayload {++ definition_id: string;++ kind: string;++ name: string;++ rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";++ issuer: string;++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "inventory.definition.manage",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "first-party",++ "description": "PLANNED (ADR-054, plan T21): Create, edit, submit and retire definitions in the caller's namespace (POST /api/v1/definitions, PATCH /api/v1/definitions/:id with inventory.definition-request@1 → inventory.definition@1). A creator's definition goes to review; a service's or app's is published when it asks. It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "inventory.definition-request@1",++ "outputSchema": "inventory.definition@1",++ "permissions": [++ "inventory:define"++ ],++ "resourceConstraints": [++ "namespace"++ ],++ "quotaClass": "inventory-write",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,17 @@++{++ "id": "inventory.definition.review",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "internal",++ "description": "PLANNED (ADR-054, plan T21): Staff publish or reject a submitted definition (POST /api/v1/definitions/:id/review → inventory.definition@1), checking safety, art rights and an honest rarity (ADR-054 §6). It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "common.no-body@1",++ "outputSchema": "inventory.definition@1",++ "permissions": [++ "inventory:review"++ ],++ "resourceConstraints": [],++ "quotaClass": "inventory-write",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "inventory.equip.manage",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "public",++ "description": "PLANNED (ADR-054, plan T21): Equip or clear a slot with an instance the person owns (PUT /api/v1/me/equipped with inventory.equip-request@1 → inventory.equipped@1). One item per slot. Refuses an instance not owned or not in state owned (409 inventory.not_owned). It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "inventory.equip-request@1",++ "outputSchema": "inventory.equipped@1",++ "permissions": [++ "inventory:own:write"++ ],++ "resourceConstraints": [++ "owner"++ ],++ "quotaClass": "inventory-write",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "inventory.item.consume",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "first-party",++ "description": "PLANNED (ADR-054, plan T21): Consume or revoke an instance of a definition the caller issued (POST /api/v1/instances/:id/consume | /revoke → inventory.instance@1). It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "common.no-body@1",++ "outputSchema": "inventory.instance@1",++ "permissions": [++ "inventory:grant"++ ],++ "resourceConstraints": [++ "namespace"++ ],++ "quotaClass": "inventory-write",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "inventory.item.grant",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "first-party",++ "description": "PLANNED (ADR-054, plan T21): Grant an instance of a definition the caller issued (POST /api/v1/grants with inventory.grant-request@1 → inventory.instance@1; Idempotency by idempotency_key). Outside the issuer's namespace: 403 inventory.not_issuer. Sold out: 409 inventory.supply_exhausted. Never for money (ADR-054 §5). It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "inventory.grant-request@1",++ "outputSchema": "inventory.instance@1",++ "permissions": [++ "inventory:grant"++ ],++ "resourceConstraints": [++ "namespace"++ ],++ "quotaClass": "inventory-write",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,19 @@++{++ "id": "inventory.item.list",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "public",++ "description": "PLANNED (ADR-054, plan T21): The person's own full inventory, consumed and revoked instances included (GET /api/v1/me/items → inventory.inventory@1). A service may read it acting for the person (on_behalf_of). It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "common.no-body@1",++ "outputSchema": "inventory.inventory@1",++ "permissions": [++ "inventory:own:read"++ ],++ "resourceConstraints": [++ "owner"++ ],++ "quotaClass": "inventory-read",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,17 @@++{++ "id": "inventory.item.read",++ "version": "1.0",++ "owner": "inventory",++ "status": "planned",++ "visibility": "public",++ "description": "PLANNED (ADR-054, plan T21): Read a person's public inventory (GET /api/v1/people/:subject/items → inventory.inventory@1: owned instances of published definitions), their equipped set (GET /api/v1/people/:subject/equipped, GET /api/v1/equipped?subjects=… up to 100 → inventory.equipped-batch@1), definitions and kinds. It becomes active when OpenVibe.Inventory implements the route.",++ "inputSchema": "common.no-body@1",++ "outputSchema": "inventory.inventory@1",++ "permissions": [++ "inventory:read"++ ],++ "resourceConstraints": [],++ "quotaClass": "inventory-read",++ "events": [],++ "implementedBy": []++}nnew file mode 100644@@@ -0,0 +1,59 @@++{++ "version": "0.0.0",++ "contractRanges": {++ "openvibe-contracts": ">=0.121.0 <1.0.0"++ },++ "id": "inventory",++ "name": "OpenVibe.Inventory",++ "status": "placeholder",++ "repository": "OpenVibers/OpenVibe.Inventory",++ "domains": [++ "inventory.openvibe.network"++ ],++ "publicOrigin": "https://inventory.openvibe.network",++ "exposure": {++ "state": "placeholder",++ "publicSite": null,++ "note": "planned (ADR-054, plan T21 step 1); nothing is built or deployed yet. Live's cosmetics stay in Live until the migration in ADR-054 §8."++ },++ "capabilities": [++ "inventory.item.read",++ "inventory.item.list",++ "inventory.equip.manage",++ "inventory.item.grant",++ "inventory.item.consume",++ "inventory.definition.manage",++ "inventory.definition.review"++ ],++ "eventsProduced": [++ "inventory.item.granted",++ "inventory.item.consumed",++ "inventory.item.revoked",++ "inventory.item.equipped",++ "inventory.item.unequipped",++ "inventory.definition.published"++ ],++ "eventsConsumed": [],++ "namespacesOwned": [],++ "lifecycle": {++ "liveness": {++ "none": "not built yet; nothing listens on a loopback address"++ },++ "shutdown": {++ "none": "not built yet; nothing runs or drains"++ },++ "startupRecovery": {++ "none": "not built yet; nothing starts"++ },++ "rollback": {++ "none": "not built yet; nothing is released or rolled back"++ },++ "contracts": {++ "range": ">=0.121.0 <1.0.0"++ },++ "leases": {++ "none": "not built yet; nothing runs"++ }++ },++ "notes": "The network-wide inventory (ADR-054): item kinds (a contract plus a renderer per surface), definitions (itd_), instances (inv_), the equipped set and an append-only ledger, in its own PostgreSQL database (ov_inventory, loopback 5030). Issuers (services, apps, creators) grant within their namespace; no selling, buying, trading or conversion until a later money ADR (ADR-012, ADR-025). Live's cosmetics become the first kinds, migrated convert-verify-delete. Profiles are Network's and read the showcase here."++}@@@ -1,12 +1,12 @@{"name": "openvibe-contracts",-- "version": "0.120.0",++ "version": "0.121.0","lockfileVersion": 3,"requires": true,"packages": {"": {"name": "openvibe-contracts",-- "version": "0.120.0",++ "version": "0.121.0","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -1,6 +1,6 @@{"name": "openvibe-contracts",-- "version": "0.120.0",++ "version": "0.121.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",
@@ -4,6 +4,24 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
@@ -4,6 +4,24 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
the notes were in the tag and commit messages (`git tag -n1`).
+## 0.121.0 — 2026-10-09
+
+**The OpenVibe inventory, decided (ADR-054, plan T21 step 1).** A new authority, OpenVibe.Inventory, will own items
+across the network: kinds, definitions, instances, the equipped set and an append-only ledger.
+- `docs/adr/ADR-054-inventory-authority.md` (accepted):
+ - service `inventory`, `ov_inventory`, loopback 5030, `inventory.openvibe.network`;
+ - issuers grant within their namespace;
+ - nothing is sold, bought, traded or converted until a later money ADR (ADR-012, ADR-025);
+ - Live's cosmetics become the first kinds, migrated convert-verify-delete.
+- `manifests/services/inventory.json` (placeholder), with seven planned capabilities: `inventory.item.read`,
+ `inventory.item.list`, `inventory.equip.manage`, `inventory.item.grant`, `inventory.item.consume`,
+ `inventory.definition.manage` and `inventory.definition.review`.
+- Schemas, with fixtures: `inventory.kind@1`, `inventory.definition@1`, `inventory.instance@1`,
+ `inventory.inventory@1`, `inventory.equipped@1`, `inventory.equipped-batch@1`, `inventory.grant-request@1`,
+ `inventory.equip-request@1` and `inventory.definition-request@1`.
+- Events: `inventory.item.granted`, `inventory.item.consumed`, `inventory.item.revoked`, `inventory.item.equipped`,
+ `inventory.item.unequipped` and `inventory.definition.published`.
+
## 0.120.0 — 2026-10-09
## 0.120.0 — 2026-10-09
**Account export and deletion everywhere a person has rows.** Nine more services declare the two account events.
**Account export and deletion everywhere a person has rows.** Nine more services declare the two account events.
@@ -6398,6 +6398,156 @@
@@ -6398,6 +6398,156 @@
"visibility": "public",
"visibility": "public",
"compatibility": "backward",
"compatibility": "backward",
"status": "active"
"status": "active"
+ },
+ {
+ "id": "inventory.kind",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/kind.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.definition",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/definition.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.instance",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/instance.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.inventory",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/inventory.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.equipped",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/equipped.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.equipped-batch",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/equipped-batch.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.grant-request",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/grant-request.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.equip-request",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/equip-request.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.definition-request",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "inventory/definition-request.v1.json",
+ "visibility": "public",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.item.granted",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "events/payloads/inventory.item.granted.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.item.consumed",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "events/payloads/inventory.item.consumed.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.item.revoked",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "events/payloads/inventory.item.revoked.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.item.equipped",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "events/payloads/inventory.item.equipped.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.item.unequipped",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "events/payloads/inventory.item.unequipped.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
+ },
+ {
+ "id": "inventory.definition.published",
+ "version": "1.0.0",
+ "owner": "inventory",
+ "schema": "events/payloads/inventory.definition.published.v1.json",
+ "visibility": "first-party",
+ "compatibility": "backward",
+ "status": "active",
+ "adr": "ADR-054"
}
}
]
]
}
}
new file mode 100644
new file mode 100644
@@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.definition.published.v1.json",
+ "title": "InventoryDefinitionPublishedPayload",
+ "description": "inventory.definition.published v1 (OpenVibe.Inventory, ADR-054). A definition became grantable (a service's on request, a creator's after review). Envelope: subject { type: item_definition, id }, visibility public.",
+ "type": "object",
+ "required": [
+ "definition_id",
+ "kind",
+ "name",
+ "rarity",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ },
+ "rarity": {
+ "enum": [
+ "common",
+ "uncommon",
+ "rare",
+ "epic",
+ "legendary"
+ ]
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.consumed.v1.json",
+ "title": "InventoryItemConsumedPayload",
+ "description": "inventory.item.consumed v1 (OpenVibe.Inventory, ADR-054). An issuer consumed an instance (a one-use item used up). Envelope: subject { type: user, id: owner }, visibility subject.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "owner",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.equipped.v1.json",
+ "title": "InventoryItemEquippedPayload",
+ "description": "inventory.item.equipped v1 (OpenVibe.Inventory, ADR-054). A person equipped an instance in a slot; surfaces drop their cached equipped set. Envelope: subject { type: user, id: owner }, visibility public.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "kind",
+ "slot",
+ "owner"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "slot": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.granted.v1.json",
+ "title": "InventoryItemGrantedPayload",
+ "description": "inventory.item.granted v1 (OpenVibe.Inventory, ADR-054). An instance was granted or earned (ADR-054 §4). Envelope: subject { type: user, id: owner }, visibility subject, actor the issuer.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "kind",
+ "owner",
+ "origin",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "origin": {
+ "enum": [
+ "granted",
+ "earned",
+ "migrated"
+ ]
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.revoked.v1.json",
+ "title": "InventoryItemRevokedPayload",
+ "description": "inventory.item.revoked v1 (OpenVibe.Inventory, ADR-054). An issuer or staff revoked an instance (granted in error, abuse). Envelope: subject { type: user, id: owner }, visibility subject.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "owner",
+ "reason"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "reason": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.unequipped.v1.json",
+ "title": "InventoryItemUnequippedPayload",
+ "description": "inventory.item.unequipped v1 (OpenVibe.Inventory, ADR-054). A person cleared a slot. Envelope: subject { type: user, id: owner }, visibility public.",
+ "type": "object",
+ "required": [
+ "kind",
+ "slot",
+ "owner"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "slot": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/definition-request.v1.json",
+ "title": "InventoryDefinitionRequest",
+ "description": "Create or edit a definition in the issuer's namespace (inventory.definition.manage). A service's or app's definition is published when it asks; a creator's goes to staff review (in_review) first.",
+ "type": "object",
+ "required": [
+ "kind",
+ "name",
+ "art",
+ "rarity"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500
+ },
+ "art": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "media_id": {
+ "type": "string",
+ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "An OpenVibe.Media object (an image, an animation)."
+ },
+ "token": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "description": "A token the kind's renderers know (a CSS class, a speech preset)."
+ },
+ "emoji": {
+ "type": "string",
+ "maxLength": 16
+ }
+ }
+ },
+ "rarity": {
+ "enum": [
+ "common",
+ "uncommon",
+ "rare",
+ "epic",
+ "legendary"
+ ]
+ },
+ "attributes": {
+ "type": "object"
+ },
+ "supply_cap": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 1
+ },
+ "aliases": {
+ "type": "array",
+ "maxItems": 8,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"
+ }
+ },
+ "publish": {
+ "type": "boolean",
+ "description": "Ask for publication (a creator's definition goes to review)."
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,147 @@
@@ -0,0 +1,147 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/definition.v1.json",
+ "title": "InventoryDefinition",
+ "description": "An item definition (ADR-054 §2): one item of a kind, issued by a service, an app or a creator, with an honest rarity, attributes valid against the kind and an optional supply cap. Published definitions can be granted; retired ones cannot, and their instances stay.",
+ "type": "object",
+ "required": [
+ "id",
+ "kind",
+ "name",
+ "art",
+ "rarity",
+ "attributes",
+ "issuer",
+ "supply",
+ "status",
+ "created_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500
+ },
+ "art": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "media_id": {
+ "type": "string",
+ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "An OpenVibe.Media object (an image, an animation)."
+ },
+ "token": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "description": "A token the kind's renderers know (a CSS class, a speech preset)."
+ },
+ "emoji": {
+ "type": "string",
+ "maxLength": 16
+ }
+ }
+ },
+ "rarity": {
+ "enum": [
+ "common",
+ "uncommon",
+ "rare",
+ "epic",
+ "legendary"
+ ],
+ "description": "Shown as is; any odds that apply are shown with it, never hidden."
+ },
+ "attributes": {
+ "type": "object"
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ },
+ "aliases": {
+ "type": "array",
+ "maxItems": 8,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"
+ },
+ "description": "Earlier ids of the same item (Live's fx_rainbow, hat_crown, …)."
+ },
+ "supply": {
+ "type": "object",
+ "required": [
+ "cap",
+ "issued"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "cap": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 1,
+ "description": "null: unlimited."
+ },
+ "issued": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ },
+ "status": {
+ "enum": [
+ "draft",
+ "in_review",
+ "published",
+ "retired"
+ ]
+ },
+ "credit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 80
+ }
+ },
+ "description": "The creator of a community item (ADR-054 §6)."
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "published_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/equip-request.v1.json",
+ "title": "InventoryEquipRequest",
+ "description": "Equip an instance the person owns in one slot of its kind, or clear the slot (instance_id null). One item per slot; equipping replaces what was there.",
+ "type": "object",
+ "required": [
+ "kind",
+ "slot",
+ "instance_id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64
+ },
+ "slot": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "instance_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/equipped-batch.v1.json",
+ "title": "InventoryEquippedBatch",
+ "description": "The equipped sets of many people at once (GET /api/v1/equipped?subjects=…, up to 100): one query on the authority, one call per chat render batch.",
+ "type": "object",
+ "required": [
+ "equipped"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "equipped": {
+ "type": "array",
+ "maxItems": 100,
+ "items": {
+ "$ref": "equipped.v1.json"
+ }
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/equipped.v1.json",
+ "title": "InventoryEquipped",
+ "description": "What a person has equipped (ADR-054 §2), keyed <kind>:<slot>. Surfaces read it in batches (inventory.equipped-batch@1) and cache it briefly.",
+ "type": "object",
+ "required": [
+ "subject",
+ "slots",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "slots": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+:[a-z][a-z0-9_]{0,31}$"
+ },
+ "additionalProperties": {
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "token": {
+ "type": "string",
+ "maxLength": 80,
+ "description": "The definition's art token, so a renderer needs no second read."
+ }
+ }
+ },
+ "description": "<kind>:<slot> → the instance in use."
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/grant-request.v1.json",
+ "title": "InventoryGrantRequest",
+ "description": "An issuer grants one instance of a definition it issued to a person (inventory.item.grant). Idempotent per idempotency_key: a repeat answers the instance already granted. A capped definition that is sold out answers 409 inventory.supply_exhausted.",
+ "type": "object",
+ "required": [
+ "definition_id",
+ "subject",
+ "idempotency_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "idempotency_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 128
+ },
+ "origin": {
+ "enum": [
+ "granted",
+ "earned"
+ ],
+ "default": "granted"
+ },
+ "reason": {
+ "type": "string",
+ "maxLength": 200,
+ "description": "Shown in the ledger: what the person did (a quest, an event, a milestone)."
+ },
+ "attributes": {
+ "type": "object"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/instance.v1.json",
+ "title": "InventoryInstance",
+ "description": "One item a person owns (ADR-054 §2): a definition, its origin and state. bought and traded are reserved for the later money ADR (ADR-054 §5) and are refused until it is accepted.",
+ "type": "object",
+ "required": [
+ "id",
+ "definition_id",
+ "owner",
+ "origin",
+ "state",
+ "acquired_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "origin": {
+ "enum": [
+ "granted",
+ "earned",
+ "migrated",
+ "bought",
+ "traded"
+ ]
+ },
+ "state": {
+ "enum": [
+ "owned",
+ "consumed",
+ "revoked"
+ ]
+ },
+ "attributes": {
+ "type": "object",
+ "description": "Per-instance values (a serial number, a wear value), valid against the kind."
+ },
+ "serial": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The instance's number within a capped supply."
+ },
+ "acquired_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/inventory.v1.json",
+ "title": "InventoryList",
+ "description": "A person's inventory page: their instances, newest first, with the definitions they refer to. The public read shows only owned instances of published definitions; the person's own read (inventory.item.list) also shows consumed and revoked ones.",
+ "type": "object",
+ "required": [
+ "subject",
+ "instances",
+ "definitions",
+ "next_cursor"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "instances": {
+ "type": "array",
+ "maxItems": 500,
+ "items": {
+ "$ref": "instance.v1.json"
+ }
+ },
+ "definitions": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "additionalProperties": {
+ "$ref": "definition.v1.json"
+ }
+ },
+ "next_cursor": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 200
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/kind.v1.json",
+ "title": "InventoryKind",
+ "description": "An item kind (ADR-054 §2): what items of the kind carry (an attribute schema), where they can be equipped (slots) and which surfaces render them. A new kind is a contract plus a renderer, never a new table.",
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "slots",
+ "surfaces",
+ "attributes",
+ "stackable",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64,
+ "description": "<namespace>.<kind>, e.g. live.name_effect, games.skin, network.badge."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500
+ },
+ "slots": {
+ "type": "array",
+ "maxItems": 16,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "description": "Where one item of the kind can be equipped; empty: the kind is not equippable (a collectible, a badge shown on the profile)."
+ },
+ "surfaces": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 16,
+ "items": {
+ "type": "object",
+ "required": [
+ "surface",
+ "renderer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "surface": {
+ "type": "string",
+ "pattern": "^(chat|overlay|profile|game:[a-z][a-z0-9-]*)$",
+ "description": "Where an item of this kind shows."
+ },
+ "renderer": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "description": "The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1."
+ }
+ }
+ }
+ },
+ "attributes": {
+ "type": "object",
+ "description": "A JSON Schema every definition's attributes must satisfy."
+ },
+ "stackable": {
+ "type": "boolean",
+ "description": "True: one person may hold several instances of one definition."
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$",
+ "description": "Who owns the kind's namespace."
+ }
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,153 @@
@@ -0,0 +1,153 @@
+# ADR-054: The OpenVibe inventory — one authority for items across the network
+
+**Status:** Accepted 2026-10-09 (plan track T21, step 1), on the owner's direction of 2026-10-08. Builds on ADR-012
+(money lives only in Billing), ADR-025 (nothing traded between people without a new ADR), ADR-029 (account merge),
+ADR-033 (account export and deletion), ADR-035 (each authority owns its PostgreSQL database) and ADR-048 (one authority
+per resource).
+
+## Context
+
+> **Owner, 2026-10-08:** "improve and overhaul/remake the inventory system to be more like steam / csgo / etc style
+> community driven and modular through sdk / api type shit rather than our current inventory seen on openvibe.live for
+> name fx and particles and all that shit it should be a cross site network wide shared multi purpose modular system
+> with user profiles and shit".
+
+What exists today is Live's cosmetics, and only Live can see them:
+
+- **The catalog is code.** `OpenVibe.Live` `server/monetization/cosmetics.js` `COSMETICS` lists name effects,
+ particles, hats and voices, each with a tier and the CSS or speech values Live renders.
+- **Ownership is two tables in Live's database.** `user_cosmetics` holds what a person unlocked (`user_id`, `item_id`,
+ `category`) and `user_equipped` holds one item per slot. On 2026-10-09 production held 153 unlock rows for 8 people
+ (voice 116, name effect 20, particle 10, hat 7) and 16 equipped slots; `user_equipped_tag` was empty.
+- **Unlocks come only from Live's own routes** (`server/monetization/cosmetics-routes.js`). Nothing else can grant,
+ show or equip an item, and nothing outside Live knows a person owns one.
+
+## Decision
+
+### 1. A new authority: OpenVibe.Inventory
+
+- **Identity:** service `inventory`, repository `OpenVibers/OpenVibe.Inventory`, loopback port 5030.
+- **Storage:** its own PostgreSQL database `ov_inventory` (ADR-035).
+- **Public read API:** `https://inventory.openvibe.network`, a Network subdomain like `api.` and `auth.`.
+- **Owns:** item kinds, definitions, instances, the equipped set and the item ledger. Nothing else holds item
+ ownership. Live keeps only the renderers for the kinds it shows.
+- **Profile pages** stay with Network, which owns people: the public profile shows the person's showcase by reading
+ Inventory.
+
+### 2. The model
+
+- **Kind** (a contract, string id `<namespace>.<kind>`, e.g. `live.name_effect`, `games.skin`, `network.badge`, `network.profile_frame`).
+ A kind declares:
+ - its attribute schema (JSON Schema);
+ - its slots, so one item of the kind can be equipped per slot and surface;
+ - the surfaces that render it (`chat`, `overlay`, `profile`, `game:<id>`), each with the renderer contract the
+ surface implements.
+
+ A new kind is a contract plus a renderer, never a new table.
+- **Definition** (`itd_<ULID>`): kind, name, description, art (a Media object or a renderer token such as a CSS class
+ the kind's renderers know), rarity, attributes valid against the kind's schema, issuer, optional supply cap and
+ status (`draft` → `in_review` → `published` → `retired`).
+ - The issuer is a service, an app (ADR-014) or a creator.
+ - Rarity is one of `common`, `uncommon`, `rare`, `epic`, `legendary`, shown with any odds that apply, never hidden.
+- **Instance** (`inv_<ULID>`): one definition owned by one subject, with its origin (`granted`, `earned`, `migrated`;
+ `bought` and `traded` are reserved for §5), acquisition time, optional per-instance attributes (a serial number, a
+ wear value) and state (`owned`, `consumed`, `revoked`).
+- **Equipped set:** per subject and slot, the instance in use. Surfaces read it in batches (many subjects in one call)
+ and cache it briefly.
+- **Ledger:** an append-only row for every movement (granted, earned, migrated, equipped, unequipped, consumed,
+ revoked, merged), with the acting principal and the reason. This is the audit trail later trading needs.
+
+### 3. Who can do what (capabilities, guarded with `requireCapability`)
+
+| Capability | Who | What |
+|---|---|---|
+| `inventory.item.read` | public | a person's public inventory and equipped set, definitions, kinds |
+| `inventory.item.list` | the person, or a service acting for them | their own full inventory, including hidden items |
+| `inventory.equip.manage` | the person, or a service acting for them | equip and unequip their own instances |
+| `inventory.item.grant` | an issuer, for definitions it issued | grant an instance to a subject (idempotent per key) |
+| `inventory.item.consume` | an issuer, for definitions it issued | consume or revoke an instance |
+| `inventory.definition.manage` | an issuer, for its namespace | create, edit, submit, retire definitions |
+| `inventory.definition.review` | staff | publish or reject a submitted definition |
+
+Apps act with grants from Services (ADR-048). A grant to an app names the definition namespace it may issue in.
+
+### 4. Events
+
+The authority publishes these on OpenVibe.Events through its outbox:
+
+- `inventory.item.granted`
+- `inventory.item.consumed`
+- `inventory.item.revoked`
+- `inventory.item.equipped`
+- `inventory.item.unequipped`
+- `inventory.definition.published`
+
+A person's own item events have visibility `subject`, and public profile changes are `public`.
+
+### 5. The money boundary
+
+ADR-012 and ADR-025 hold until a later ADR changes them.
+
+- **Not in v1:** items are not sold, bought, traded between people, cashed out or converted into OpenCoins or Vibes.
+ There are no drops, cases or paid random rewards.
+- **What a later ADR must cover first:** trading with escrow and confirmation, a marketplace priced in OpenCoins and
+ Vibes, and a creator revenue share. It must give the legal basis per country, the Billing flows (ADR-012
+ classification of every item that can be traded), trade holds, fraud and dispute handling, and minors' protection.
+- **Allowed now:** issuers grant items for things people do (a quest, an event, a stream milestone, a game
+ achievement), and staff grant them.
+
+### 6. Community items (the Workshop)
+
+- Creators submit definitions in their own namespace (`creator.<username>.*`).
+- Review covers safety, art rights and honest rarity before anything is published.
+- A published item credits its creator. A revenue share waits for §5's ADR.
+
+### 7. Account data and merge
+
+- **Export (ADR-033):** the person's instances, equipped set and ledger rows.
+- **Deletion:** their instances and equipped set are deleted, and their ledger rows lose their subject, which keeps the
+ supply counts true. A creator's published definitions stay, with the creator credit removed.
+- **Merge (ADR-029):** instances move to the surviving subject, and duplicates of a unique definition keep the oldest.
+
+### 8. Live's cosmetics are the first kinds (convert, verify, delete)
+
+1. **Convert:**
+ - Kinds `live.name_effect`, `live.particle`, `live.hat`, `live.voice` and `live.chat_tag` are registered.
+ - Each `COSMETICS` entry becomes a definition issued by `live`, keeping its id as an alias. Tier maps to rarity:
+ 1 common, 2 uncommon, 3 rare, 4 epic, 5 and 6 legendary.
+ - Every `user_cosmetics` row becomes an instance with origin `migrated`, and every `user_equipped` row becomes the
+ equipped slot.
+2. **Verify:** each person's unlocked set and equipped slots match, row for row, on both sides.
+3. **Switch:** Live reads through Inventory, behind a Live setting `INVENTORY_AUTHORITY` (`live` until the switch, then
+ `inventory`). Its routes become calls to Inventory with Live's service token acting for the person.
+4. **Delete:** after the N-1 window, a contract migration drops `user_cosmetics`, `user_equipped` and
+ `user_equipped_tag`. Live keeps the CSS and speech renderers.
+
+## Alternatives considered
+
+- **Inside Network** (the wallet and profile area): rejected.
+ - Network is identity and the money ledger, and an inventory has its own lifecycle, write load (grants from every
+ game and site) and review queue.
+ - Keeping it apart keeps the ADR-012 boundary visible: an item is never a balance.
+- **Inside Live:** rejected, because items must work across every site.
+- **Inside Games:** rejected, because Live, Chat, Community and the profile also show items, and Games is one issuer
+ among many.
+
+## Rollback
+
+- **Before the Live switch:** stop the Inventory service; Live still reads its own tables.
+- **After the switch and before the delete:** set `INVENTORY_AUTHORITY=live`. Live writes no item rows while switched,
+ so anything granted in between is replayed from the Inventory ledger.
+
+## Acceptance tests
+
+- A kind's schema refuses a definition with invalid attributes, and a renderer is chosen per surface from the kind.
+- A grant is idempotent per key, honours the supply cap, and writes one ledger row and one `inventory.item.granted`.
+- An issuer cannot grant, consume or edit outside its namespace, and staff review is required to publish a creator's
+ definition.
+- Equip refuses an instance the person does not own or that is consumed, and holds one item per slot.
+- A batch read of equipped sets for 100 subjects is one query.
+- No route sells, buys, trades or converts an item (a route-inventory test, as for Trade).
+- Live's migration verifies row for row before the switch; Live renders the same name effects, particles, hats and
+ voices after it.
+- Export, deletion and merge behave as in §7.
@@ -47,3 +47,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each
@@ -47,3 +47,4 @@ Platform-wide decisions from the OpenVibe development roadmap (section 10). Each
| [ADR-046](ADR-046-universal-adaptive-fabric.md) | The universal adaptive fabric: offers, requirements, placement results and signed plans through one placer (`openvibe-sdk/placement`); health, cost, telemetry and usage samples; five trust classes, with `user-owned` eligible only when a workload names it; `worker:<class>` Node capabilities; the data plane keeps running on the last valid signed plan; T6 AI the reference consumer | Proposed 2026-10-03 (plan T1 step 3), for the owner's review |
| [ADR-046](ADR-046-universal-adaptive-fabric.md) | The universal adaptive fabric: offers, requirements, placement results and signed plans through one placer (`openvibe-sdk/placement`); health, cost, telemetry and usage samples; five trust classes, with `user-owned` eligible only when a workload names it; `worker:<class>` Node capabilities; the data plane keeps running on the last valid signed plan; T6 AI the reference consumer | Proposed 2026-10-03 (plan T1 step 3), for the owner's review |
| [ADR-048](ADR-048-services-control-plane.md) | The Services control plane: Services aggregates authorities and owns no other service's rows; every console action is a `common.resource-control-request@1` to the owning authority, answered with `common.resource-control-result@1` (idempotency keys, `confirmation_id` for sensitive actions); OVRN `ovrn:<service>:<project_id>:<type>/<id>` (`common.resource-name@1`) is the one cross-service resource name | Accepted 2026-10-04 (plan T13) |
| [ADR-048](ADR-048-services-control-plane.md) | The Services control plane: Services aggregates authorities and owns no other service's rows; every console action is a `common.resource-control-request@1` to the owning authority, answered with `common.resource-control-result@1` (idempotency keys, `confirmation_id` for sensitive actions); OVRN `ovrn:<service>:<project_id>:<type>/<id>` (`common.resource-name@1`) is the one cross-service resource name | Accepted 2026-10-04 (plan T13) |
| [ADR-053](ADR-053-website-host-boundary.md) | The Website/Host boundary: OpenVibe.Website owns authoring (projects, pages, revisions, builds, Media asset pointers and intended domains) and OpenVibe.Host owns site, deploy, activation, domain binding/verification/TLS and serving; Website keeps no duplicate `host_sites`/`host_deploys` rows and calls Host's routes; a Website build is not a Host deploy; Website composes Host + Codes + Actor + Run + Media and is not OpenVibe.Sites | Proposed 2026-10-05 (plan T19), for the owner's review |
| [ADR-053](ADR-053-website-host-boundary.md) | The Website/Host boundary: OpenVibe.Website owns authoring (projects, pages, revisions, builds, Media asset pointers and intended domains) and OpenVibe.Host owns site, deploy, activation, domain binding/verification/TLS and serving; Website keeps no duplicate `host_sites`/`host_deploys` rows and calls Host's routes; a Website build is not a Host deploy; Website composes Host + Codes + Actor + Run + Media and is not OpenVibe.Sites | Proposed 2026-10-05 (plan T19), for the owner's review |
+| [ADR-054](ADR-054-inventory-authority.md) | The OpenVibe inventory: a new authority, OpenVibe.Inventory (`inventory`, `ov_inventory`), owns item kinds (contract + renderer per surface), definitions (`itd_`), instances (`inv_`), the equipped set and an append-only ledger; issuers grant within their namespace; no selling, buying, trading or conversion until a later money ADR (ADR-012/ADR-025); Live's cosmetics are the first kinds, migrated convert-verify-delete | Accepted 2026-10-09 (plan T21) |
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "kind": "network.profile_frame",
+ "name": "x",
+ "rarity": "rare"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "kind": "network.profile_frame",
+ "name": "Aurora frame",
+ "art": {
+ "media_id": "med_01JZ0000000000000000000MED"
+ },
+ "rarity": "rare",
+ "supply_cap": 500,
+ "publish": true
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "kind": "network.profile_frame",
+ "name": "Aurora frame",
+ "rarity": "rare",
+ "issuer": "user:usr_01JZ0000000000000000000AAA"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001T2",
+ "kind": "network.profile_frame",
+ "name": "Aurora frame",
+ "rarity": "rare",
+ "issuer": "user:usr_01JZ0000000000000000000AAA"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
+{
+ "id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "name": "Rainbow Name",
+ "description": "Rainbow cycling colors",
+ "art": {
+ "token": "name-fx-rainbow",
+ "emoji": "🌈"
+ },
+ "rarity": "common",
+ "attributes": {
+ "css_class": "name-fx-rainbow"
+ },
+ "issuer": "live",
+ "aliases": [
+ "fx_rainbow"
+ ],
+ "supply": {
+ "cap": null,
+ "issued": 4
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
+{
+ "id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "name": "Rainbow Name",
+ "description": "Rainbow cycling colors",
+ "art": {
+ "token": "name-fx-rainbow",
+ "emoji": "🌈"
+ },
+ "rarity": "mythic",
+ "attributes": {
+ "css_class": "name-fx-rainbow"
+ },
+ "issuer": "service:live",
+ "aliases": [
+ "fx_rainbow"
+ ],
+ "supply": {
+ "cap": null,
+ "issued": 4
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
+{
+ "id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "name": "Rainbow Name",
+ "description": "Rainbow cycling colors",
+ "art": {},
+ "rarity": "common",
+ "attributes": {
+ "css_class": "name-fx-rainbow"
+ },
+ "issuer": "service:live",
+ "aliases": [
+ "fx_rainbow"
+ ],
+ "supply": {
+ "cap": null,
+ "issued": 4
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
+{
+ "id": "itd_01JZ00000000000000000001T2",
+ "kind": "network.profile_frame",
+ "name": "Aurora frame",
+ "description": "Rainbow cycling colors",
+ "art": {
+ "media_id": "med_01JZ0000000000000000000MED"
+ },
+ "rarity": "rare",
+ "attributes": {},
+ "issuer": "user:usr_01JZ0000000000000000000AAA",
+ "aliases": [],
+ "supply": {
+ "cap": 500,
+ "issued": 12
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z",
+ "credit": {
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "name": "aurora_artist"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
+{
+ "id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "name": "Rainbow Name",
+ "description": "Rainbow cycling colors",
+ "art": {
+ "token": "name-fx-rainbow",
+ "emoji": "🌈"
+ },
+ "rarity": "common",
+ "attributes": {
+ "css_class": "name-fx-rainbow"
+ },
+ "issuer": "service:live",
+ "aliases": [
+ "fx_rainbow"
+ ],
+ "supply": {
+ "cap": null,
+ "issued": 4
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "kind": "live.hat",
+ "instance_id": "inv_01JZ00000000000000000001NV"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "kind": "live.hat",
+ "slot": "hat",
+ "instance_id": null
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "kind": "live.name_effect",
+ "slot": "name_effect",
+ "instance_id": "inv_01JZ00000000000000000001NV"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
+{
+ "equipped": {
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "slots": {
+ "live.name_effect:name_effect": {
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "token": "name-fx-rainbow"
+ }
+ },
+ "updated_at": "2026-10-09T03:00:00Z"
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
+{
+ "equipped": [
+ {
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "slots": {
+ "live.name_effect:name_effect": {
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "token": "name-fx-rainbow"
+ }
+ },
+ "updated_at": "2026-10-09T03:00:00Z"
+ },
+ {
+ "subject": "usr_01JZ0000000000000000000BBB",
+ "slots": {},
+ "updated_at": "2026-10-09T03:00:00Z"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
+{
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "slots": {
+ "name_effect": {
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD"
+ }
+ },
+ "updated_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "subject": "usr_01JZ0000000000000000000BBB",
+ "slots": {},
+ "updated_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
+{
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "slots": {
+ "live.name_effect:name_effect": {
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "token": "name-fx-rainbow"
+ }
+ },
+ "updated_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "idempotency_key": "k-12345678",
+ "origin": "bought"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "idempotency_key": "k"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "idempotency_key": "quest-0000-0001",
+ "origin": "earned",
+ "reason": "Completed the first-stream quest"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "gst_01JZ0000000000000000000AAA",
+ "origin": "migrated",
+ "state": "owned",
+ "acquired_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "origin": "migrated",
+ "state": "sold",
+ "acquired_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "origin": "migrated",
+ "state": "owned",
+ "acquired_at": "2026-10-09T03:00:00Z"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
+{
+ "id": "inv_01JZ00000000000000000001N2",
+ "definition_id": "itd_01JZ00000000000000000001T2",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "origin": "earned",
+ "state": "owned",
+ "acquired_at": "2026-10-09T03:00:00Z",
+ "serial": 12,
+ "attributes": {
+ "wear": 0.1
+ }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
+{
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "instances": [],
+ "definitions": {
+ "fx_rainbow": {
+ "id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "name": "Rainbow Name",
+ "description": "Rainbow cycling colors",
+ "art": {
+ "token": "name-fx-rainbow",
+ "emoji": "🌈"
+ },
+ "rarity": "common",
+ "attributes": {
+ "css_class": "name-fx-rainbow"
+ },
+ "issuer": "service:live",
+ "aliases": [
+ "fx_rainbow"
+ ],
+ "supply": {
+ "cap": null,
+ "issued": 4
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z"
+ }
+ },
+ "next_cursor": null
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "instances": [],
+ "definitions": {}
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "subject": "usr_01JZ0000000000000000000BBB",
+ "instances": [],
+ "definitions": {},
+ "next_cursor": null
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
+{
+ "subject": "usr_01JZ0000000000000000000AAA",
+ "instances": [
+ {
+ "id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "origin": "migrated",
+ "state": "owned",
+ "acquired_at": "2026-10-09T03:00:00Z"
+ }
+ ],
+ "definitions": {
+ "itd_01JZ00000000000000000001TD": {
+ "id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "name": "Rainbow Name",
+ "description": "Rainbow cycling colors",
+ "art": {
+ "token": "name-fx-rainbow",
+ "emoji": "🌈"
+ },
+ "rarity": "common",
+ "attributes": {
+ "css_class": "name-fx-rainbow"
+ },
+ "issuer": "service:live",
+ "aliases": [
+ "fx_rainbow"
+ ],
+ "supply": {
+ "cap": null,
+ "issued": 4
+ },
+ "status": "published",
+ "created_at": "2026-10-09T03:00:00Z",
+ "updated_at": "2026-10-09T03:00:00Z",
+ "published_at": "2026-10-09T03:00:00Z"
+ }
+ },
+ "next_cursor": null
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "issuer": "service:games"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "issuer": "service:games"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "slot": "name_effect",
+ "owner": "usr_01JZ0000000000000000000AAA"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "slot": "name_effect",
+ "owner": "usr_01JZ0000000000000000000AAA"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "origin": "earned",
+ "issuer": "service:quest"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
+{
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "kind": "live.name_effect",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "origin": "earned",
+ "issuer": "service:quest"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "reason": "granted twice by mistake"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
+{
+ "instance_id": "inv_01JZ00000000000000000001NV",
+ "definition_id": "itd_01JZ00000000000000000001TD",
+ "owner": "usr_01JZ0000000000000000000AAA",
+ "reason": "granted twice by mistake"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
+{
+ "slot": "hat",
+ "owner": "usr_01JZ0000000000000000000AAA"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
+{
+ "kind": "live.hat",
+ "slot": "hat",
+ "owner": "usr_01JZ0000000000000000000AAA"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
+{
+ "id": "NameEffect",
+ "name": "Name effect",
+ "description": "How your name looks in chat.",
+ "slots": [
+ "name_effect"
+ ],
+ "surfaces": [
+ {
+ "surface": "chat",
+ "renderer": "live.name_effect.css@1"
+ },
+ {
+ "surface": "profile",
+ "renderer": "live.name_effect.css@1"
+ }
+ ],
+ "attributes": {
+ "type": "object",
+ "required": [
+ "css_class"
+ ],
+ "properties": {
+ "css_class": {
+ "type": "string"
+ }
+ }
+ },
+ "stackable": false,
+ "issuer": "service:live"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
+{
+ "id": "live.name_effect",
+ "name": "Name effect",
+ "description": "How your name looks in chat.",
+ "slots": [
+ "name_effect"
+ ],
+ "surfaces": [
+ {
+ "surface": "billboard",
+ "renderer": "x"
+ }
+ ],
+ "attributes": {
+ "type": "object",
+ "required": [
+ "css_class"
+ ],
+ "properties": {
+ "css_class": {
+ "type": "string"
+ }
+ }
+ },
+ "stackable": false,
+ "issuer": "service:live"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
+{
+ "id": "live.name_effect",
+ "name": "Name effect",
+ "description": "How your name looks in chat.",
+ "slots": [
+ "name_effect"
+ ],
+ "surfaces": [],
+ "attributes": {
+ "type": "object",
+ "required": [
+ "css_class"
+ ],
+ "properties": {
+ "css_class": {
+ "type": "string"
+ }
+ }
+ },
+ "stackable": false,
+ "issuer": "service:live"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
+{
+ "id": "network.badge",
+ "name": "Badge",
+ "description": "How your name looks in chat.",
+ "slots": [],
+ "surfaces": [
+ {
+ "surface": "profile",
+ "renderer": "network.badge.img@1"
+ }
+ ],
+ "attributes": {
+ "type": "object",
+ "required": [
+ "css_class"
+ ],
+ "properties": {
+ "css_class": {
+ "type": "string"
+ }
+ }
+ },
+ "stackable": true,
+ "issuer": "service:network"
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
+{
+ "id": "live.name_effect",
+ "name": "Name effect",
+ "description": "How your name looks in chat.",
+ "slots": [
+ "name_effect"
+ ],
+ "surfaces": [
+ {
+ "surface": "chat",
+ "renderer": "live.name_effect.css@1"
+ },
+ {
+ "surface": "profile",
+ "renderer": "live.name_effect.css@1"
+ }
+ ],
+ "attributes": {
+ "type": "object",
+ "required": [
+ "css_class"
+ ],
+ "properties": {
+ "css_class": {
+ "type": "string"
+ }
+ }
+ },
+ "stackable": false,
+ "issuer": "service:live"
+}
@@ -73814,6 +73814,861 @@
@@ -73814,6 +73814,861 @@
}
}
]
]
}
}
+ },
+ "inventory.kind": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/kind.v1.json",
+ "title": "InventoryKind",
+ "description": "An item kind (ADR-054 §2): what items of the kind carry (an attribute schema), where they can be equipped (slots) and which surfaces render them. A new kind is a contract plus a renderer, never a new table.",
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "slots",
+ "surfaces",
+ "attributes",
+ "stackable",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64,
+ "description": "<namespace>.<kind>, e.g. live.name_effect, games.skin, network.badge."
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500
+ },
+ "slots": {
+ "type": "array",
+ "maxItems": 16,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "description": "Where one item of the kind can be equipped; empty: the kind is not equippable (a collectible, a badge shown on the profile)."
+ },
+ "surfaces": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 16,
+ "items": {
+ "type": "object",
+ "required": [
+ "surface",
+ "renderer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "surface": {
+ "type": "string",
+ "pattern": "^(chat|overlay|profile|game:[a-z][a-z0-9-]*)$",
+ "description": "Where an item of this kind shows."
+ },
+ "renderer": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "description": "The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1."
+ }
+ }
+ }
+ },
+ "attributes": {
+ "type": "object",
+ "description": "A JSON Schema every definition's attributes must satisfy."
+ },
+ "stackable": {
+ "type": "boolean",
+ "description": "True: one person may hold several instances of one definition."
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$",
+ "description": "Who owns the kind's namespace."
+ }
+ }
+ }
+ },
+ "inventory.definition": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/definition.v1.json",
+ "title": "InventoryDefinition",
+ "description": "An item definition (ADR-054 §2): one item of a kind, issued by a service, an app or a creator, with an honest rarity, attributes valid against the kind and an optional supply cap. Published definitions can be granted; retired ones cannot, and their instances stay.",
+ "type": "object",
+ "required": [
+ "id",
+ "kind",
+ "name",
+ "art",
+ "rarity",
+ "attributes",
+ "issuer",
+ "supply",
+ "status",
+ "created_at",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500
+ },
+ "art": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "media_id": {
+ "type": "string",
+ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "An OpenVibe.Media object (an image, an animation)."
+ },
+ "token": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "description": "A token the kind's renderers know (a CSS class, a speech preset)."
+ },
+ "emoji": {
+ "type": "string",
+ "maxLength": 16
+ }
+ }
+ },
+ "rarity": {
+ "enum": [
+ "common",
+ "uncommon",
+ "rare",
+ "epic",
+ "legendary"
+ ],
+ "description": "Shown as is; any odds that apply are shown with it, never hidden."
+ },
+ "attributes": {
+ "type": "object"
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ },
+ "aliases": {
+ "type": "array",
+ "maxItems": 8,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"
+ },
+ "description": "Earlier ids of the same item (Live's fx_rainbow, hat_crown, …)."
+ },
+ "supply": {
+ "type": "object",
+ "required": [
+ "cap",
+ "issued"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "cap": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 1,
+ "description": "null: unlimited."
+ },
+ "issued": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ },
+ "status": {
+ "enum": [
+ "draft",
+ "in_review",
+ "published",
+ "retired"
+ ]
+ },
+ "credit": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 80
+ }
+ },
+ "description": "The creator of a community item (ADR-054 §6)."
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "published_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ },
+ "inventory.instance": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/instance.v1.json",
+ "title": "InventoryInstance",
+ "description": "One item a person owns (ADR-054 §2): a definition, its origin and state. bought and traded are reserved for the later money ADR (ADR-054 §5) and are refused until it is accepted.",
+ "type": "object",
+ "required": [
+ "id",
+ "definition_id",
+ "owner",
+ "origin",
+ "state",
+ "acquired_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "origin": {
+ "enum": [
+ "granted",
+ "earned",
+ "migrated",
+ "bought",
+ "traded"
+ ]
+ },
+ "state": {
+ "enum": [
+ "owned",
+ "consumed",
+ "revoked"
+ ]
+ },
+ "attributes": {
+ "type": "object",
+ "description": "Per-instance values (a serial number, a wear value), valid against the kind."
+ },
+ "serial": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "The instance's number within a capped supply."
+ },
+ "acquired_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ },
+ "inventory.inventory": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/inventory.v1.json",
+ "title": "InventoryList",
+ "description": "A person's inventory page: their instances, newest first, with the definitions they refer to. The public read shows only owned instances of published definitions; the person's own read (inventory.item.list) also shows consumed and revoked ones.",
+ "type": "object",
+ "required": [
+ "subject",
+ "instances",
+ "definitions",
+ "next_cursor"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "instances": {
+ "type": "array",
+ "maxItems": 500,
+ "items": {
+ "$ref": "instance.v1.json"
+ }
+ },
+ "definitions": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "additionalProperties": {
+ "$ref": "definition.v1.json"
+ }
+ },
+ "next_cursor": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 200
+ }
+ }
+ }
+ },
+ "inventory.equipped": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/equipped.v1.json",
+ "title": "InventoryEquipped",
+ "description": "What a person has equipped (ADR-054 §2), keyed <kind>:<slot>. Surfaces read it in batches (inventory.equipped-batch@1) and cache it briefly.",
+ "type": "object",
+ "required": [
+ "subject",
+ "slots",
+ "updated_at"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "slots": {
+ "type": "object",
+ "propertyNames": {
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+:[a-z][a-z0-9_]{0,31}$"
+ },
+ "additionalProperties": {
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "token": {
+ "type": "string",
+ "maxLength": 80,
+ "description": "The definition's art token, so a renderer needs no second read."
+ }
+ }
+ },
+ "description": "<kind>:<slot> → the instance in use."
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ }
+ },
+ "inventory.equipped-batch": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/equipped-batch.v1.json",
+ "title": "InventoryEquippedBatch",
+ "description": "The equipped sets of many people at once (GET /api/v1/equipped?subjects=…, up to 100): one query on the authority, one call per chat render batch.",
+ "type": "object",
+ "required": [
+ "equipped"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "equipped": {
+ "type": "array",
+ "maxItems": 100,
+ "items": {
+ "$ref": "equipped.v1.json"
+ }
+ }
+ }
+ }
+ },
+ "inventory.grant-request": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/grant-request.v1.json",
+ "title": "InventoryGrantRequest",
+ "description": "An issuer grants one instance of a definition it issued to a person (inventory.item.grant). Idempotent per idempotency_key: a repeat answers the instance already granted. A capped definition that is sold out answers 409 inventory.supply_exhausted.",
+ "type": "object",
+ "required": [
+ "definition_id",
+ "subject",
+ "idempotency_key"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "subject": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "idempotency_key": {
+ "type": "string",
+ "minLength": 8,
+ "maxLength": 128
+ },
+ "origin": {
+ "enum": [
+ "granted",
+ "earned"
+ ],
+ "default": "granted"
+ },
+ "reason": {
+ "type": "string",
+ "maxLength": 200,
+ "description": "Shown in the ledger: what the person did (a quest, an event, a milestone)."
+ },
+ "attributes": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "inventory.equip-request": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/equip-request.v1.json",
+ "title": "InventoryEquipRequest",
+ "description": "Equip an instance the person owns in one slot of its kind, or clear the slot (instance_id null). One item per slot; equipping replaces what was there.",
+ "type": "object",
+ "required": [
+ "kind",
+ "slot",
+ "instance_id"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64
+ },
+ "slot": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "instance_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+ }
+ },
+ "inventory.definition-request": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/inventory/definition-request.v1.json",
+ "title": "InventoryDefinitionRequest",
+ "description": "Create or edit a definition in the issuer's namespace (inventory.definition.manage). A service's or app's definition is published when it asks; a creator's goes to staff review (in_review) first.",
+ "type": "object",
+ "required": [
+ "kind",
+ "name",
+ "art",
+ "rarity"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$",
+ "maxLength": 64
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80
+ },
+ "description": {
+ "type": "string",
+ "maxLength": 500
+ },
+ "art": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "media_id": {
+ "type": "string",
+ "pattern": "^med_[0-9A-HJKMNP-TV-Z]{26}$",
+ "description": "An OpenVibe.Media object (an image, an animation)."
+ },
+ "token": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 80,
+ "description": "A token the kind's renderers know (a CSS class, a speech preset)."
+ },
+ "emoji": {
+ "type": "string",
+ "maxLength": 16
+ }
+ }
+ },
+ "rarity": {
+ "enum": [
+ "common",
+ "uncommon",
+ "rare",
+ "epic",
+ "legendary"
+ ]
+ },
+ "attributes": {
+ "type": "object"
+ },
+ "supply_cap": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 1
+ },
+ "aliases": {
+ "type": "array",
+ "maxItems": 8,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_.-]{0,63}$"
+ }
+ },
+ "publish": {
+ "type": "boolean",
+ "description": "Ask for publication (a creator's definition goes to review)."
+ }
+ }
+ }
+ },
+ "inventory.item.granted": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.granted.v1.json",
+ "title": "InventoryItemGrantedPayload",
+ "description": "inventory.item.granted v1 (OpenVibe.Inventory, ADR-054). An instance was granted or earned (ADR-054 §4). Envelope: subject { type: user, id: owner }, visibility subject, actor the issuer.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "kind",
+ "owner",
+ "origin",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "origin": {
+ "enum": [
+ "granted",
+ "earned",
+ "migrated"
+ ]
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ }
+ }
+ }
+ },
+ "inventory.item.consumed": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.consumed.v1.json",
+ "title": "InventoryItemConsumedPayload",
+ "description": "inventory.item.consumed v1 (OpenVibe.Inventory, ADR-054). An issuer consumed an instance (a one-use item used up). Envelope: subject { type: user, id: owner }, visibility subject.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "owner",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ }
+ }
+ }
+ },
+ "inventory.item.revoked": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.revoked.v1.json",
+ "title": "InventoryItemRevokedPayload",
+ "description": "inventory.item.revoked v1 (OpenVibe.Inventory, ADR-054). An issuer or staff revoked an instance (granted in error, abuse). Envelope: subject { type: user, id: owner }, visibility subject.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "owner",
+ "reason"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "reason": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ }
+ }
+ }
+ },
+ "inventory.item.equipped": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.equipped.v1.json",
+ "title": "InventoryItemEquippedPayload",
+ "description": "inventory.item.equipped v1 (OpenVibe.Inventory, ADR-054). A person equipped an instance in a slot; surfaces drop their cached equipped set. Envelope: subject { type: user, id: owner }, visibility public.",
+ "type": "object",
+ "required": [
+ "instance_id",
+ "definition_id",
+ "kind",
+ "slot",
+ "owner"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "instance_id": {
+ "type": "string",
+ "pattern": "^inv_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "slot": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+ }
+ },
+ "inventory.item.unequipped": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.item.unequipped.v1.json",
+ "title": "InventoryItemUnequippedPayload",
+ "description": "inventory.item.unequipped v1 (OpenVibe.Inventory, ADR-054). A person cleared a slot. Envelope: subject { type: user, id: owner }, visibility public.",
+ "type": "object",
+ "required": [
+ "kind",
+ "slot",
+ "owner"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "slot": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]{0,31}$"
+ },
+ "owner": {
+ "type": "string",
+ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$"
+ }
+ }
+ }
+ },
+ "inventory.definition.published": {
+ "version": "1.0.0",
+ "owner": "inventory",
+ "status": "active",
+ "schema": {
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openvibe.network/contracts/events/payloads/inventory.definition.published.v1.json",
+ "title": "InventoryDefinitionPublishedPayload",
+ "description": "inventory.definition.published v1 (OpenVibe.Inventory, ADR-054). A definition became grantable (a service's on request, a creator's after review). Envelope: subject { type: item_definition, id }, visibility public.",
+ "type": "object",
+ "required": [
+ "definition_id",
+ "kind",
+ "name",
+ "rarity",
+ "issuer"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "definition_id": {
+ "type": "string",
+ "pattern": "^itd_[0-9A-HJKMNP-TV-Z]{26}$"
+ },
+ "kind": {
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)+$"
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ },
+ "rarity": {
+ "enum": [
+ "common",
+ "uncommon",
+ "rare",
+ "epic",
+ "legendary"
+ ]
+ },
+ "issuer": {
+ "type": "string",
+ "pattern": "^(service:[a-z][a-z0-9-]*|app:app_[0-9A-HJKMNP-TV-Z]{26}|user:usr_[0-9A-HJKMNP-TV-Z]{26})$"
+ }
+ }
+ }
}
}
}
}
}
}
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Actor API",
"title": "OpenVibe.Actor API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"title": "OpenVibe.AI API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"title": "OpenVibe.Billing API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"title": "OpenVibe.Blog API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bot API",
"title": "OpenVibe.Bot API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Chat API",
"title": "OpenVibe.Chat API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Community API",
"title": "OpenVibe.Community API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Coupons API",
"title": "OpenVibe.Coupons API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Deals API",
"title": "OpenVibe.Deals API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Events API",
"title": "OpenVibe.Events API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Food API",
"title": "OpenVibe.Food API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Games API",
"title": "OpenVibe.Games API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Host API",
"title": "OpenVibe.Host API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"title": "OpenVibe.Live API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Media API",
"title": "OpenVibe.Media API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Network API",
"title": "OpenVibe.Network API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.News API",
"title": "OpenVibe.News API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRe.Stream API",
"title": "OpenRe.Stream API",
- "version": "0.120.0",
- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Reviews API",
"title": "OpenVibe.Reviews API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Run API",
"title": "OpenVibe.Run API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Search API",
"title": "OpenVibe.Search API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Services API",
"title": "OpenVibe.Services API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Sources API",
"title": "OpenVibe.Sources API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tips API",
"title": "OpenVibe.Tips API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tools API",
"title": "OpenVibe.Tools API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Trade API",
"title": "OpenVibe.Trade API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.VIP API",
"title": "OpenVibe.VIP API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Watch API",
"title": "OpenVibe.Watch API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Wiki API",
"title": "OpenVibe.Wiki API",
- "version": "0.120.0",
- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.120.0): each operation lists the capabilities it performs; a token for 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.121.0",
+ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.121.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -59044,3 +59044,1750 @@ export type FoodPlanResult =
@@ -59044,3 +59044,1750 @@ export type FoodPlanResult =
plans: FoodPlan[];
plans: FoodPlan[];
}
}
| FoodPlan;
| FoodPlan;
+
+/** [email protected] (owner: inventory) */
+/**
+ * An item kind (ADR-054 §2): what items of the kind carry (an attribute schema), where they can be equipped (slots) and which surfaces render them. A new kind is a contract plus a renderer, never a new table.
+ */
+export interface InventoryKind {
+ /**
+ * <namespace>.<kind>, e.g. live.name_effect, games.skin, network.badge.
+ */
+ id: string;
+ name: string;
+ description?: string;
+ /**
+ * Where one item of the kind can be equipped; empty: the kind is not equippable (a collectible, a badge shown on the profile).
+ *
+ * @maxItems 16
+ */
+ slots:
+ | []
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ]
+ | [
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string,
+ string
+ ];
+ /**
+ * @minItems 1
+ * @maxItems 16
+ */
+ surfaces:
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ]
+ | [
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ },
+ {
+ /**
+ * Where an item of this kind shows.
+ */
+ surface: string;
+ /**
+ * The renderer contract the surface implements for this kind, e.g. live.name_effect.css@1.
+ */
+ renderer: string;
+ }
+ ];
+ /**
+ * A JSON Schema every definition's attributes must satisfy.
+ */
+ attributes: {};
+ /**
+ * True: one person may hold several instances of one definition.
+ */
+ stackable: boolean;
+ /**
+ * Who owns the kind's namespace.
+ */
+ issuer: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * An item definition (ADR-054 §2): one item of a kind, issued by a service, an app or a creator, with an honest rarity, attributes valid against the kind and an optional supply cap. Published definitions can be granted; retired ones cannot, and their instances stay.
+ */
+export interface InventoryDefinition {
+ id: string;
+ kind: string;
+ name: string;
+ description?: string;
+ art: {
+ /**
+ * An OpenVibe.Media object (an image, an animation).
+ */
+ media_id?: string;
+ /**
+ * A token the kind's renderers know (a CSS class, a speech preset).
+ */
+ token?: string;
+ emoji?: string;
+ };
+ /**
+ * Shown as is; any odds that apply are shown with it, never hidden.
+ */
+ rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";
+ attributes: {};
+ issuer: string;
+ /**
+ * Earlier ids of the same item (Live's fx_rainbow, hat_crown, …).
+ *
+ * @maxItems 8
+ */
+ aliases?:
+ | []
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string];
+ supply: {
+ /**
+ * null: unlimited.
+ */
+ cap: number | null;
+ issued: number;
+ };
+ status: "draft" | "in_review" | "published" | "retired";
+ /**
+ * The creator of a community item (ADR-054 §6).
+ */
+ credit?: {
+ subject?: string;
+ name?: string;
+ };
+ created_at: string;
+ updated_at: string;
+ published_at?: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * One item a person owns (ADR-054 §2): a definition, its origin and state. bought and traded are reserved for the later money ADR (ADR-054 §5) and are refused until it is accepted.
+ */
+export interface InventoryInstance {
+ id: string;
+ definition_id: string;
+ owner: string;
+ origin: "granted" | "earned" | "migrated" | "bought" | "traded";
+ state: "owned" | "consumed" | "revoked";
+ /**
+ * Per-instance values (a serial number, a wear value), valid against the kind.
+ */
+ attributes?: {};
+ /**
+ * The instance's number within a capped supply.
+ */
+ serial?: number;
+ acquired_at: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * A person's inventory page: their instances, newest first, with the definitions they refer to. The public read shows only owned instances of published definitions; the person's own read (inventory.item.list) also shows consumed and revoked ones.
+ */
+export interface InventoryList {
+ subject: string;
+ /**
+ * @maxItems 500
+ */
+ instances: InventoryInstance[];
+ definitions: {
+ [k: string]: InventoryDefinition | undefined;
+ };
+ next_cursor: string | null;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * What a person has equipped (ADR-054 §2), keyed <kind>:<slot>. Surfaces read it in batches (inventory.equipped-batch@1) and cache it briefly.
+ */
+export interface InventoryEquipped {
+ subject: string;
+ /**
+ * <kind>:<slot> → the instance in use.
+ */
+ slots: {
+ [k: string]:
+ | {
+ instance_id: string;
+ definition_id: string;
+ /**
+ * The definition's art token, so a renderer needs no second read.
+ */
+ token?: string;
+ }
+ | undefined;
+ };
+ updated_at: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * The equipped sets of many people at once (GET /api/v1/equipped?subjects=…, up to 100): one query on the authority, one call per chat render batch.
+ */
+export interface InventoryEquippedBatch {
+ /**
+ * @maxItems 100
+ */
+ equipped: InventoryEquipped[];
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * An issuer grants one instance of a definition it issued to a person (inventory.item.grant). Idempotent per idempotency_key: a repeat answers the instance already granted. A capped definition that is sold out answers 409 inventory.supply_exhausted.
+ */
+export interface InventoryGrantRequest {
+ definition_id: string;
+ subject: string;
+ idempotency_key: string;
+ origin?: "granted" | "earned";
+ /**
+ * Shown in the ledger: what the person did (a quest, an event, a milestone).
+ */
+ reason?: string;
+ attributes?: {};
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * Equip an instance the person owns in one slot of its kind, or clear the slot (instance_id null). One item per slot; equipping replaces what was there.
+ */
+export interface InventoryEquipRequest {
+ kind: string;
+ slot: string;
+ instance_id: string | null;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * Create or edit a definition in the issuer's namespace (inventory.definition.manage). A service's or app's definition is published when it asks; a creator's goes to staff review (in_review) first.
+ */
+export interface InventoryDefinitionRequest {
+ kind: string;
+ name: string;
+ description?: string;
+ art: {
+ /**
+ * An OpenVibe.Media object (an image, an animation).
+ */
+ media_id?: string;
+ /**
+ * A token the kind's renderers know (a CSS class, a speech preset).
+ */
+ token?: string;
+ emoji?: string;
+ };
+ rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";
+ attributes?: {};
+ supply_cap?: number | null;
+ /**
+ * @maxItems 8
+ */
+ aliases?:
+ | []
+ | [string]
+ | [string, string]
+ | [string, string, string]
+ | [string, string, string, string]
+ | [string, string, string, string, string]
+ | [string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string]
+ | [string, string, string, string, string, string, string, string];
+ /**
+ * Ask for publication (a creator's definition goes to review).
+ */
+ publish?: boolean;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * inventory.item.granted v1 (OpenVibe.Inventory, ADR-054). An instance was granted or earned (ADR-054 §4). Envelope: subject { type: user, id: owner }, visibility subject, actor the issuer.
+ */
+export interface InventoryItemGrantedPayload {
+ instance_id: string;
+ definition_id: string;
+ kind: string;
+ owner: string;
+ origin: "granted" | "earned" | "migrated";
+ issuer: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * inventory.item.consumed v1 (OpenVibe.Inventory, ADR-054). An issuer consumed an instance (a one-use item used up). Envelope: subject { type: user, id: owner }, visibility subject.
+ */
+export interface InventoryItemConsumedPayload {
+ instance_id: string;
+ definition_id: string;
+ owner: string;
+ issuer: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * inventory.item.revoked v1 (OpenVibe.Inventory, ADR-054). An issuer or staff revoked an instance (granted in error, abuse). Envelope: subject { type: user, id: owner }, visibility subject.
+ */
+export interface InventoryItemRevokedPayload {
+ instance_id: string;
+ definition_id: string;
+ owner: string;
+ reason: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * inventory.item.equipped v1 (OpenVibe.Inventory, ADR-054). A person equipped an instance in a slot; surfaces drop their cached equipped set. Envelope: subject { type: user, id: owner }, visibility public.
+ */
+export interface InventoryItemEquippedPayload {
+ instance_id: string;
+ definition_id: string;
+ kind: string;
+ slot: string;
+ owner: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * inventory.item.unequipped v1 (OpenVibe.Inventory, ADR-054). A person cleared a slot. Envelope: subject { type: user, id: owner }, visibility public.
+ */
+export interface InventoryItemUnequippedPayload {
+ kind: string;
+ slot: string;
+ owner: string;
+}
+
+/** [email protected] (owner: inventory) */
+/**
+ * inventory.definition.published v1 (OpenVibe.Inventory, ADR-054). A definition became grantable (a service's on request, a creator's after review). Envelope: subject { type: item_definition, id }, visibility public.
+ */
+export interface InventoryDefinitionPublishedPayload {
+ definition_id: string;
+ kind: string;
+ name: string;
+ rarity: "common" | "uncommon" | "rare" | "epic" | "legendary";
+ issuer: string;
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "inventory.definition.manage",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "first-party",
+ "description": "PLANNED (ADR-054, plan T21): Create, edit, submit and retire definitions in the caller's namespace (POST /api/v1/definitions, PATCH /api/v1/definitions/:id with inventory.definition-request@1 → inventory.definition@1). A creator's definition goes to review; a service's or app's is published when it asks. It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "inventory.definition-request@1",
+ "outputSchema": "inventory.definition@1",
+ "permissions": [
+ "inventory:define"
+ ],
+ "resourceConstraints": [
+ "namespace"
+ ],
+ "quotaClass": "inventory-write",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
+{
+ "id": "inventory.definition.review",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "internal",
+ "description": "PLANNED (ADR-054, plan T21): Staff publish or reject a submitted definition (POST /api/v1/definitions/:id/review → inventory.definition@1), checking safety, art rights and an honest rarity (ADR-054 §6). It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "common.no-body@1",
+ "outputSchema": "inventory.definition@1",
+ "permissions": [
+ "inventory:review"
+ ],
+ "resourceConstraints": [],
+ "quotaClass": "inventory-write",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "inventory.equip.manage",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "public",
+ "description": "PLANNED (ADR-054, plan T21): Equip or clear a slot with an instance the person owns (PUT /api/v1/me/equipped with inventory.equip-request@1 → inventory.equipped@1). One item per slot. Refuses an instance not owned or not in state owned (409 inventory.not_owned). It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "inventory.equip-request@1",
+ "outputSchema": "inventory.equipped@1",
+ "permissions": [
+ "inventory:own:write"
+ ],
+ "resourceConstraints": [
+ "owner"
+ ],
+ "quotaClass": "inventory-write",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "inventory.item.consume",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "first-party",
+ "description": "PLANNED (ADR-054, plan T21): Consume or revoke an instance of a definition the caller issued (POST /api/v1/instances/:id/consume | /revoke → inventory.instance@1). It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "common.no-body@1",
+ "outputSchema": "inventory.instance@1",
+ "permissions": [
+ "inventory:grant"
+ ],
+ "resourceConstraints": [
+ "namespace"
+ ],
+ "quotaClass": "inventory-write",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "inventory.item.grant",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "first-party",
+ "description": "PLANNED (ADR-054, plan T21): Grant an instance of a definition the caller issued (POST /api/v1/grants with inventory.grant-request@1 → inventory.instance@1; Idempotency by idempotency_key). Outside the issuer's namespace: 403 inventory.not_issuer. Sold out: 409 inventory.supply_exhausted. Never for money (ADR-054 §5). It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "inventory.grant-request@1",
+ "outputSchema": "inventory.instance@1",
+ "permissions": [
+ "inventory:grant"
+ ],
+ "resourceConstraints": [
+ "namespace"
+ ],
+ "quotaClass": "inventory-write",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
+{
+ "id": "inventory.item.list",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "public",
+ "description": "PLANNED (ADR-054, plan T21): The person's own full inventory, consumed and revoked instances included (GET /api/v1/me/items → inventory.inventory@1). A service may read it acting for the person (on_behalf_of). It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "common.no-body@1",
+ "outputSchema": "inventory.inventory@1",
+ "permissions": [
+ "inventory:own:read"
+ ],
+ "resourceConstraints": [
+ "owner"
+ ],
+ "quotaClass": "inventory-read",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
+{
+ "id": "inventory.item.read",
+ "version": "1.0",
+ "owner": "inventory",
+ "status": "planned",
+ "visibility": "public",
+ "description": "PLANNED (ADR-054, plan T21): Read a person's public inventory (GET /api/v1/people/:subject/items → inventory.inventory@1: owned instances of published definitions), their equipped set (GET /api/v1/people/:subject/equipped, GET /api/v1/equipped?subjects=… up to 100 → inventory.equipped-batch@1), definitions and kinds. It becomes active when OpenVibe.Inventory implements the route.",
+ "inputSchema": "common.no-body@1",
+ "outputSchema": "inventory.inventory@1",
+ "permissions": [
+ "inventory:read"
+ ],
+ "resourceConstraints": [],
+ "quotaClass": "inventory-read",
+ "events": [],
+ "implementedBy": []
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
+{
+ "version": "0.0.0",
+ "contractRanges": {
+ "openvibe-contracts": ">=0.121.0 <1.0.0"
+ },
+ "id": "inventory",
+ "name": "OpenVibe.Inventory",
+ "status": "placeholder",
+ "repository": "OpenVibers/OpenVibe.Inventory",
+ "domains": [
+ "inventory.openvibe.network"
+ ],
+ "publicOrigin": "https://inventory.openvibe.network",
+ "exposure": {
+ "state": "placeholder",
+ "publicSite": null,
+ "note": "planned (ADR-054, plan T21 step 1); nothing is built or deployed yet. Live's cosmetics stay in Live until the migration in ADR-054 §8."
+ },
+ "capabilities": [
+ "inventory.item.read",
+ "inventory.item.list",
+ "inventory.equip.manage",
+ "inventory.item.grant",
+ "inventory.item.consume",
+ "inventory.definition.manage",
+ "inventory.definition.review"
+ ],
+ "eventsProduced": [
+ "inventory.item.granted",
+ "inventory.item.consumed",
+ "inventory.item.revoked",
+ "inventory.item.equipped",
+ "inventory.item.unequipped",
+ "inventory.definition.published"
+ ],
+ "eventsConsumed": [],
+ "namespacesOwned": [],
+ "lifecycle": {
+ "liveness": {
+ "none": "not built yet; nothing listens on a loopback address"
+ },
+ "shutdown": {
+ "none": "not built yet; nothing runs or drains"
+ },
+ "startupRecovery": {
+ "none": "not built yet; nothing starts"
+ },
+ "rollback": {
+ "none": "not built yet; nothing is released or rolled back"
+ },
+ "contracts": {
+ "range": ">=0.121.0 <1.0.0"
+ },
+ "leases": {
+ "none": "not built yet; nothing runs"
+ }
+ },
+ "notes": "The network-wide inventory (ADR-054): item kinds (a contract plus a renderer per surface), definitions (itd_), instances (inv_), the equipped set and an append-only ledger, in its own PostgreSQL database (ov_inventory, loopback 5030). Issuers (services, apps, creators) grant within their namespace; no selling, buying, trading or conversion until a later money ADR (ADR-012, ADR-025). Live's cosmetics become the first kinds, migrated convert-verify-delete. Profiles are Network's and read the showcase here."
+}
@@ -1,12 +1,12 @@
@@ -1,12 +1,12 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.120.0",
+ "version": "0.121.0",
"lockfileVersion": 3,
"lockfileVersion": 3,
"requires": true,
"requires": true,
"packages": {
"packages": {
"": {
"": {
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.120.0",
+ "version": "0.121.0",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"name": "openvibe-contracts",
- "version": "0.120.0",
+ "version": "0.121.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",