openvibers/openvibe.contracts Commits

v0.60.0: release manifest 1.2.0 (roadmap WS-P task 7, ADR-016 amendment 2): client_generation, min_client_generation (a tab below it reloads when safe, reason required) and shell { version, components } (a tab whose shell differs is prompted, never updated in place); fixtures

OP OpenVibers committed 26 Sept 2026 · f3852ee9f7 · 34 files, +482 −52


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex ebc4eb2d..3a486224 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,15 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
++## 0.60.0 — 2026-09-26
++
++**Release manifest 1.2.0** (`registry.release-manifest`, roadmap WS-P task 7, ADR-016 amendment 2). Three optional fields:
++- `client_generation`: the generation of the client this release serves.
++- `min_client_generation`: a tab below it reloads at the next safe moment (reason `required`).
++- `shell`: `{ version, components }`. A tab whose shell differs is prompted, never updated in place.
++
++Fixtures cover a full 1.2.0 manifest, a negative generation and a bad shell version. Additive.
++
## 0.59.0 — 2026-09-26
**Media namespaces and grants** (roadmap WS-G task 2). Media's grants are five verbs, each one capability checked per namespace: read (`media.object.read`), list, write (`media.object.upload`), delete and transform (`media.derivative.create`).
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex f3b12e61..82813bc1 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -155,7 +155,7 @@
},
{
"id": "registry.release-manifest",
-- "version": "1.1.0",
++ "version": "1.2.0",
"owner": "network",
"schema": "registry/release-manifest.v1.json",
"visibility": "public",
ddiff --git a/contracts/registry/release-manifest.v1.json b/contracts/registry/release-manifest.v1.json
iindex 52c94499..6fdc4ede 100644
---- a/contracts/registry/release-manifest.v1.json
++++ b/contracts/registry/release-manifest.v1.json
@@@ -80,6 +80,26 @@
"type": ["string", "null"],
"maxLength": 512,
"description": "Since 1.1.0. Same-origin URL where clients POST their update outcome counts (applied, reloaded, deferred, failed); null or absent when the service does not collect them."
++ },
++ "client_generation": {
++ "type": ["integer", "null"],
++ "minimum": 0,
++ "description": "Since 1.2.0. The generation of the client this release serves (its pages and scripts). It goes up only when an older client can no longer work against this server; the page carries it in the ov-release meta tag's data-generation. Null when the service does not track one."
++ },
++ "min_client_generation": {
++ "type": ["integer", "null"],
++ "minimum": 0,
++ "description": "Since 1.2.0. Oldest client generation still supported: an open tab whose generation is lower reloads at the next safe moment (reason required), without waiting for the mixed-version window. Null when every generation in the window is."
++ },
++ "shell": {
++ "type": ["object", "null"],
++ "additionalProperties": false,
++ "required": ["version", "components"],
++ "description": "Since 1.2.0. The page shell (layout, router, navigation): the ids of the components that make it up and one version over them. A tab whose shell version differs never updates in place; it is prompted, and reloads only when it must. Null when the service names no shell.",
++ "properties": {
++ "version": { "type": "string", "pattern": "^[0-9a-f]{12}$", "description": "The first 12 hex of SHA-256 over the shell components' ids and versions, in id order." },
++ "components": { "type": "array", "maxItems": 20, "items": { "type": "string", "pattern": "^[a-z][a-z0-9-]{0,39}$" }, "description": "Ids from components." }
++ }
}
}
}
ddiff --git a/docs/adr/ADR-016-active-client-updates.md b/docs/adr/ADR-016-active-client-updates.md
iindex 8df99210..efbda418 100644
---- a/docs/adr/ADR-016-active-client-updates.md
++++ b/docs/adr/ADR-016-active-client-updates.md
@@@ -66,3 +66,13 @@ Roadmap WS-P task 9.
only the poll.
- **Rollback.** Stop announcing (`--no-announce`, or remove the credentials): tabs fall back to polling,
as before.
++
++## Amendment 2 (2026-09-26): client generations and the shell (manifest 1.2.0)
++
++Roadmap WS-P task 7 completes the release manifest with three optional fields.
++
++- **`client_generation`**: the generation of the client a release serves. It goes up only when an older client can no longer work against the server. The page states it in the `ov-release` meta tag (`data-generation`).
++- **`min_client_generation`**: the oldest generation still supported. A tab below it reloads at the next safe moment with reason `required`, without waiting for the mixed-version window. `min_client_release` stays as it is: it names one exact release, while a generation covers every release since the break.
++- **`shell`**: the page shell, `{ version, components }`. The components are ids from `components`, and the version is the first 12 hex of SHA-256 over their ids and versions. A tab whose shell version differs never updates in place: it is prompted, and reloads only when it must.
++
++The fields are additive; a client that does not know them behaves as under 1.1.0.
ddiff --git a/fixtures/registry.release-manifest/invalid/negative-generation.json b/fixtures/registry.release-manifest/invalid/negative-generation.json
nnew file mode 100644
iindex 00000000..75d5ccc0
---- /dev/null
++++ b/fixtures/registry.release-manifest/invalid/negative-generation.json
@@@ -0,0 +1,65 @@
++{
++ "service": "live",
++ "release": "047f2069a1b2",
++ "released_at": "2026-09-23T18:02:11Z",
++ "booted_at": "2026-09-23T18:04:40Z",
++ "contracts_version": "0.31.0",
++ "packages": {
++ "openvibe-shared": "1.5.0",
++ "openvibe-sdk": "0.4.0"
++ },
++ "min_client_release": null,
++ "mixed_version_window_hours": 24,
++ "components": {
++ "styles": {
++ "kind": "style",
++ "version": "3f9a1c07be21"
++ },
++ "docs": {
++ "kind": "content",
++ "version": "a07e44d1c9f0"
++ },
++ "shell": {
++ "kind": "script",
++ "version": "c1d2e3f4a5b6"
++ },
++ "server": {
++ "kind": "server",
++ "version": "047f2069a1b2"
++ }
++ },
++ "assets": {
++ "/css/app.css": {
++ "url": "/css/app.css?v=3f9a1c07be21",
++ "component": "styles",
++ "integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
++ },
++ "/js/app.js": {
++ "url": "/js/app.js?v=9b8a7c6d5e4f",
++ "component": "shell"
++ }
++ },
++ "schema_generation": 42,
++ "schema_compatible_from": 40,
++ "contract_ranges": {
++ "live.web-api": {
++ "version": "1.4.0",
++ "accepts": ">=1.0.0 <2.0.0"
++ },
++ "media.object": {
++ "version": "1.0.0",
++ "accepts": ">=1.0.0 <2.0.0",
++ "role": "consumes"
++ }
++ },
++ "metrics_url": "/release-metrics",
++ "client_generation": 3,
++ "min_client_generation": -1,
++ "shell": {
++ "version": "0123456789ab",
++ "components": [
++ "styles",
++ "docs"
++ ]
++ }
++}
\\ No newline at end of file
ddiff --git a/fixtures/registry.release-manifest/invalid/shell-version-not-hex.json b/fixtures/registry.release-manifest/invalid/shell-version-not-hex.json
nnew file mode 100644
iindex 00000000..6c7487b6
---- /dev/null
++++ b/fixtures/registry.release-manifest/invalid/shell-version-not-hex.json
@@@ -0,0 +1,62 @@
++{
++ "service": "live",
++ "release": "047f2069a1b2",
++ "released_at": "2026-09-23T18:02:11Z",
++ "booted_at": "2026-09-23T18:04:40Z",
++ "contracts_version": "0.31.0",
++ "packages": {
++ "openvibe-shared": "1.5.0",
++ "openvibe-sdk": "0.4.0"
++ },
++ "min_client_release": null,
++ "mixed_version_window_hours": 24,
++ "components": {
++ "styles": {
++ "kind": "style",
++ "version": "3f9a1c07be21"
++ },
++ "docs": {
++ "kind": "content",
++ "version": "a07e44d1c9f0"
++ },
++ "shell": {
++ "kind": "script",
++ "version": "c1d2e3f4a5b6"
++ },
++ "server": {
++ "kind": "server",
++ "version": "047f2069a1b2"
++ }
++ },
++ "assets": {
++ "/css/app.css": {
++ "url": "/css/app.css?v=3f9a1c07be21",
++ "component": "styles",
++ "integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
++ },
++ "/js/app.js": {
++ "url": "/js/app.js?v=9b8a7c6d5e4f",
++ "component": "shell"
++ }
++ },
++ "schema_generation": 42,
++ "schema_compatible_from": 40,
++ "contract_ranges": {
++ "live.web-api": {
++ "version": "1.4.0",
++ "accepts": ">=1.0.0 <2.0.0"
++ },
++ "media.object": {
++ "version": "1.0.0",
++ "accepts": ">=1.0.0 <2.0.0",
++ "role": "consumes"
++ }
++ },
++ "metrics_url": "/release-metrics",
++ "client_generation": 3,
++ "min_client_generation": 2,
++ "shell": {
++ "version": "not-hex",
++ "components": []
++ }
++}
\\ No newline at end of file
ddiff --git a/fixtures/registry.release-manifest/valid/live-generations.json b/fixtures/registry.release-manifest/valid/live-generations.json
nnew file mode 100644
iindex 00000000..5113e60c
---- /dev/null
++++ b/fixtures/registry.release-manifest/valid/live-generations.json
@@@ -0,0 +1,65 @@
++{
++ "service": "live",
++ "release": "047f2069a1b2",
++ "released_at": "2026-09-23T18:02:11Z",
++ "booted_at": "2026-09-23T18:04:40Z",
++ "contracts_version": "0.31.0",
++ "packages": {
++ "openvibe-shared": "1.5.0",
++ "openvibe-sdk": "0.4.0"
++ },
++ "min_client_release": null,
++ "mixed_version_window_hours": 24,
++ "components": {
++ "styles": {
++ "kind": "style",
++ "version": "3f9a1c07be21"
++ },
++ "docs": {
++ "kind": "content",
++ "version": "a07e44d1c9f0"
++ },
++ "shell": {
++ "kind": "script",
++ "version": "c1d2e3f4a5b6"
++ },
++ "server": {
++ "kind": "server",
++ "version": "047f2069a1b2"
++ }
++ },
++ "assets": {
++ "/css/app.css": {
++ "url": "/css/app.css?v=3f9a1c07be21",
++ "component": "styles",
++ "integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
++ },
++ "/js/app.js": {
++ "url": "/js/app.js?v=9b8a7c6d5e4f",
++ "component": "shell"
++ }
++ },
++ "schema_generation": 42,
++ "schema_compatible_from": 40,
++ "contract_ranges": {
++ "live.web-api": {
++ "version": "1.4.0",
++ "accepts": ">=1.0.0 <2.0.0"
++ },
++ "media.object": {
++ "version": "1.0.0",
++ "accepts": ">=1.0.0 <2.0.0",
++ "role": "consumes"
++ }
++ },
++ "metrics_url": "/release-metrics",
++ "client_generation": 3,
++ "min_client_generation": 2,
++ "shell": {
++ "version": "0123456789ab",
++ "components": [
++ "styles",
++ "docs"
++ ]
++ }
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex 73bf8e1b..bdf380de 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -1963,7 +1963,7 @@
}
},
"registry.release-manifest": {
-- "version": "1.1.0",
++ "version": "1.2.0",
"owner": "network",
"status": "active",
"schema": {
@@@ -2143,6 +2143,50 @@
],
"maxLength": 512,
"description": "Since 1.1.0. Same-origin URL where clients POST their update outcome counts (applied, reloaded, deferred, failed); null or absent when the service does not collect them."
++ },
++ "client_generation": {
++ "type": [
++ "integer",
++ "null"
++ ],
++ "minimum": 0,
++ "description": "Since 1.2.0. The generation of the client this release serves (its pages and scripts). It goes up only when an older client can no longer work against this server; the page carries it in the ov-release meta tag's data-generation. Null when the service does not track one."
++ },
++ "min_client_generation": {
++ "type": [
++ "integer",
++ "null"
++ ],
++ "minimum": 0,
++ "description": "Since 1.2.0. Oldest client generation still supported: an open tab whose generation is lower reloads at the next safe moment (reason required), without waiting for the mixed-version window. Null when every generation in the window is."
++ },
++ "shell": {
++ "type": [
++ "object",
++ "null"
++ ],
++ "additionalProperties": false,
++ "required": [
++ "version",
++ "components"
++ ],
++ "description": "Since 1.2.0. The page shell (layout, router, navigation): the ids of the components that make it up and one version over them. A tab whose shell version differs never updates in place; it is prompted, and reloads only when it must. Null when the service names no shell.",
++ "properties": {
++ "version": {
++ "type": "string",
++ "pattern": "^[0-9a-f]{12}$",
++ "description": "The first 12 hex of SHA-256 over the shell components' ids and versions, in id order."
++ },
++ "components": {
++ "type": "array",
++ "maxItems": 20,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{0,39}$"
++ },
++ "description": "Ids from components."
++ }
++ }
}
}
}
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex 42f32eba..c1ad3945 100644
---- a/generated/openapi/ai.json
++++ b/generated/openapi/ai.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.AI API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/billing.json b/generated/openapi/billing.json
iindex 174d37d6..df383568 100644
---- a/generated/openapi/billing.json
++++ b/generated/openapi/billing.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Billing API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/blog.json b/generated/openapi/blog.json
iindex 62774a46..b20b359a 100644
---- a/generated/openapi/blog.json
++++ b/generated/openapi/blog.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Blog API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/chat.json b/generated/openapi/chat.json
iindex 3930d939..9da17d6e 100644
---- a/generated/openapi/chat.json
++++ b/generated/openapi/chat.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Chat API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/codes.json b/generated/openapi/codes.json
iindex 80b90dd4..a93649ae 100644
---- a/generated/openapi/codes.json
++++ b/generated/openapi/codes.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Codes API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/community.json b/generated/openapi/community.json
iindex cd3280c9..7ed9ee71 100644
---- a/generated/openapi/community.json
++++ b/generated/openapi/community.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Community API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/coupons.json b/generated/openapi/coupons.json
iindex bc3a5dd0..24bb0e97 100644
---- a/generated/openapi/coupons.json
++++ b/generated/openapi/coupons.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Coupons API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/deals.json b/generated/openapi/deals.json
iindex 4ec63b58..1afe8d99 100644
---- a/generated/openapi/deals.json
++++ b/generated/openapi/deals.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Deals API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/events.json b/generated/openapi/events.json
iindex 65ffadd9..d76c4756 100644
---- a/generated/openapi/events.json
++++ b/generated/openapi/events.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Events API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/games.json b/generated/openapi/games.json
iindex a66f3302..37df716e 100644
---- a/generated/openapi/games.json
++++ b/generated/openapi/games.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Games API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/host.json b/generated/openapi/host.json
iindex 57a0d1c4..20041532 100644
---- a/generated/openapi/host.json
++++ b/generated/openapi/host.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Host API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex 6c240de7..766f9bd7 100644
---- a/generated/openapi/live.json
++++ b/generated/openapi/live.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Live API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/media.json b/generated/openapi/media.json
iindex 7b494410..fd2dd218 100644
---- a/generated/openapi/media.json
++++ b/generated/openapi/media.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Media API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/network.json b/generated/openapi/network.json
iindex c6f8db0d..3a0ba0fd 100644
---- a/generated/openapi/network.json
++++ b/generated/openapi/network.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Network API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex a507eac6..8c3f46cc 100644
---- a/generated/openapi/news.json
++++ b/generated/openapi/news.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.News API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/openre.json b/generated/openapi/openre.json
iindex 979775ed..cb293bc3 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRe.Stream API",
-- "version": "0.59.0",
-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/reviews.json b/generated/openapi/reviews.json
iindex 705e5701..f3c09a36 100644
---- a/generated/openapi/reviews.json
++++ b/generated/openapi/reviews.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Reviews API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/search.json b/generated/openapi/search.json
iindex e7e9118e..0115aa7f 100644
---- a/generated/openapi/search.json
++++ b/generated/openapi/search.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Search API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/sources.json b/generated/openapi/sources.json
iindex 0dbb6807..42eae883 100644
---- a/generated/openapi/sources.json
++++ b/generated/openapi/sources.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Sources API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/tips.json b/generated/openapi/tips.json
iindex 6577273e..e69a08bf 100644
---- a/generated/openapi/tips.json
++++ b/generated/openapi/tips.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tips API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/tools.json b/generated/openapi/tools.json
iindex b447b5a5..a3703dde 100644
---- a/generated/openapi/tools.json
++++ b/generated/openapi/tools.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tools API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/trade.json b/generated/openapi/trade.json
iindex c2a41ec5..4d867016 100644
---- a/generated/openapi/trade.json
++++ b/generated/openapi/trade.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Trade API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/vip.json b/generated/openapi/vip.json
iindex 9d1cb18a..9c792744 100644
---- a/generated/openapi/vip.json
++++ b/generated/openapi/vip.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.VIP API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/wiki.json b/generated/openapi/wiki.json
iindex 3aefded4..0545f650 100644
---- a/generated/openapi/wiki.json
++++ b/generated/openapi/wiki.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Wiki API",
-- "version": "0.59.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.59.0): each operation lists the capabilities it performs; a token for 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.60.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.60.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex 5bbd243c..75432ed0 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -781,7 +781,7 @@ export interface ModuleRecord {
updated_by?: string;
}
--/** [email protected] (owner: network) */
++/** [email protected] (owner: network) */
/**
* What a running web surface is serving (GET /release.json, ADR-016). Open clients compare it on focus and reconnect. A client outside the supported window is prompted and reloads only when that is safe. Since 1.1.0 the manifest can also say which components changed, so a client can apply style and content changes in place, and which contract versions the server still accepts, so a mixed-version population can be checked.
*/
@@@ -870,6 +870,161 @@ export interface ReleaseManifest {
* Since 1.1.0. Same-origin URL where clients POST their update outcome counts (applied, reloaded, deferred, failed); null or absent when the service does not collect them.
*/
metrics_url?: string | null;
++ /**
++ * Since 1.2.0. The generation of the client this release serves (its pages and scripts). It goes up only when an older client can no longer work against this server; the page carries it in the ov-release meta tag's data-generation. Null when the service does not track one.
++ */
++ client_generation?: number | null;
++ /**
++ * Since 1.2.0. Oldest client generation still supported: an open tab whose generation is lower reloads at the next safe moment (reason required), without waiting for the mixed-version window. Null when every generation in the window is.
++ */
++ min_client_generation?: number | null;
++ /**
++ * Since 1.2.0. The page shell (layout, router, navigation): the ids of the components that make it up and one version over them. A tab whose shell version differs never updates in place; it is prompted, and reloads only when it must. Null when the service names no shell.
++ */
++ shell?: {
++ /**
++ * The first 12 hex of SHA-256 over the shell components' ids and versions, in id order.
++ */
++ version: string;
++ /**
++ * Ids from components.
++ *
++ * @maxItems 20
++ */
++ components:
++ | []
++ | [string]
++ | [string, string]
++ | [string, string, string]
++ | [string, string, string, string]
++ | [string, string, string, string, string]
++ | [string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string, string, string]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ];
++ } | null;
}
/** [email protected] (owner: common) */
ddiff --git a/package.json b/package.json
iindex efd86ddb..a5cd6255 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.59.0",
++ "version": "0.60.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",