openvibers/openvibe.contracts Commits

Subject assertions: the claims contract and the ADR-003 amendment (#306)

OP OpenVibers committed 7 days ago · 88b740160f · 55 files, +424 −88

* Subject assertions: the claims contract and the ADR-003 amendment

* Only a Network token for Network's own API may ask for an assertion

* The ADR says how the flag is turned on

* Merge main into the branch (the locked sharing release)

* 0.297.0: the subject-assertion claims contract (H1)

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex b5146aab..35a46be1 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -1,5 +1,8 @@
# Changelog
++## 0.297.0 — 2026-11-06
++
++- Add `identity.subject-assertion-claims@1`: the claims of a short-lived ES256 assertion signed by OpenVibe.Network that says a person allowed one service to act for them on another service — `sub` (the person), `aud` (the service it is for), `act` (the service it was minted for), optionally `for` (the services that may carry it), `jti`, `iat`, `exp`. Network mints one only from the person's own access token (`POST /internal/subject-assertions`), so a service that merely knows a person's id cannot say the person allowed anything; the key is published in Network's JWKS (`kid ov-network-assertion-1`). The money routes of Billing and Tips check it against the person they act for, and refuse the old "the service vouches for its person" way once `BILLING_REQUIRE_SUBJECT_ASSERTION` / `TIPS_REQUIRE_SUBJECT_ASSERTION` is on. Only a service token Network issued for its own API (`openvibe.network`) mints one. See the ADR-003 amendment of 2026-11-06.
## 0.296.0 — 2026-11-06
- Sharing learns locked items. `share.update-request@1` gains `envelope`: a `locker.envelope@1`, base64, the content re-sealed for the people who stay, sent with the members that remain when someone is removed from a people-locked item. The service stores it before it drops the member; it never opens it.
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex bb940599..621817b9 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -31,6 +31,16 @@
"status": "active",
"adr": "ADR-003"
},
++ {
++ "id": "identity.subject-assertion-claims",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "identity/subject-assertion-claims.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active",
++ "adr": "ADR-003"
++ },
{
"id": "identity.realtime-ticket-claims",
"version": "1.0.0",
ddiff --git a/contracts/identity/subject-assertion-claims.v1.json b/contracts/identity/subject-assertion-claims.v1.json
nnew file mode 100644
iindex 00000000..2672f034
---- /dev/null
++++ b/contracts/identity/subject-assertion-claims.v1.json
@@@ -0,0 +1,68 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/identity/subject-assertion-claims.v1.json",
++ "title": "SubjectAssertionClaims",
++ "description": "Claims of a short-lived ES256 assertion signed by OpenVibe.Network that says a person allowed one service to act for them on another service (ADR-003, amendment 2026-11-06; plan H1). Minted only from the person's own Network access token (POST /internal/subject-assertions): without that token nothing is signed. Carried on a money call in X-OV-Subject-Assertion. The signature key is published in Network's JWKS (kid ov-network-assertion-1, kty EC, alg ES256) beside the RS256 session key, so a receiver verifies it offline.",
++ "type": "object",
++ "required": [
++ "iss",
++ "sub",
++ "aud",
++ "act",
++ "jti",
++ "iat",
++ "exp"
++ ],
++ "additionalProperties": true,
++ "properties": {
++ "iss": {
++ "type": "string",
++ "format": "uri",
++ "description": "Issuer; https://openvibe.network in production. The receiver checks it against the issuer it expects."
++ },
++ "sub": {
++ "type": "string",
++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",
++ "description": "The person the assertion is about: their canonical subject. The receiver refuses an assertion that does not name the person the route acts for."
++ },
++ "aud": {
++ "type": "array",
++ "minItems": 1,
++ "items": {
++ "type": "string",
++ "pattern": "^openvibe\\.[a-z0-9][a-z0-9.-]*$"
++ },
++ "description": "The service(s) the assertion is for. A receiver accepts it only when its own audience is in the list. A list is used when the assertion travels a chain (a tip goes from the site to Tips and on to Billing)."
++ },
++ "act": {
++ "type": "string",
++ "pattern": "^svc:[a-z][a-z0-9-]{1,39}$",
++ "description": "The service the assertion was minted for (the one that held the person's token). It is the only service that may present it, unless `for` names others."
++ },
++ "for": {
++ "type": "array",
++ "items": {
++ "type": "string",
++ "pattern": "^svc:[a-z][a-z0-9-]{1,39}$"
++ },
++ "description": "The services that may carry the assertion (the minting service is always in it). A receiver presented by a service that is not in this list refuses the assertion (403 assertion.actor_mismatch)."
++ },
++ "jti": {
++ "type": "string",
++ "minLength": 8,
++ "description": "Unique per assertion. A receiver remembers the jtis it has seen for the replay window and refuses a second use (403 assertion.replayed)."
++ },
++ "iat": {
++ "type": "integer",
++ "description": "Issued at (seconds since the epoch)."
++ },
++ "exp": {
++ "type": "integer",
++ "description": "Expires at (seconds since the epoch). The assertion lives 60 seconds."
++ },
++ "nbf": {
++ "type": "integer",
++ "description": "Not before (seconds since the epoch). Optional; a receiver forgives a small clock difference."
++ }
++ }
++}
ddiff --git a/docs/adr/ADR-003-service-principals.md b/docs/adr/ADR-003-service-principals.md
iindex cf5a72b7..0ef456b7 100644
---- a/docs/adr/ADR-003-service-principals.md
++++ b/docs/adr/ADR-003-service-principals.md
@@@ -1,6 +1,6 @@
# ADR-003: Service/app principal authentication and capability grants
--**Status:** Accepted, implemented 2026-09-22. Amended 2026-09-24: delegated authorization semantics and approval UX (roadmap §28.3). Amended 2026-10-12: project delegation (`X-OV-Project`).
++**Status:** Accepted, implemented 2026-09-22. Amended 2026-09-24: delegated authorization semantics and approval UX (roadmap §28.3). Amended 2026-10-12: project delegation (`X-OV-Project`). Amended 2026-11-06: subject assertions on the money routes (`X-OV-Subject-Assertion`).
## Context and current evidence
@@@ -149,3 +149,80 @@ the person runs. This amendment lets a first-party service name that project, an
member is accepted and the record names project, person and `via`.
- Network: the member read needs `network.project.member.read`; a non-member and an unknown project are both 404
`project.member_not_found`.
++
++## Amendment 2026-11-06: subject assertions on money routes (plan H1)
++
++The rule above ("a first-party service may name **any** person in `X-OV-Subject`; the service vouches for its own
++signed-in user") is too much to believe on a money route. Any first-party service that knew a person's id could
++read their transactions or tip in their name, and a compromised service would be able to do both. On the money
++routes the person's own answer is required instead of the service's word: a **subject assertion**.
++
++### The rule
++
++- **A subject assertion is a Network-signed, 60-second ES256 JWT that says the person allowed one service to act for
++ them on another service.** The claims are `identity.subject-assertion-claims@1`: `iss`, `sub` (the person,
++ `usr_…`), `aud` (the service the assertion is for), `act` (the service it was minted for), `jti`, `iat`, `exp`, and
++ optionally `for` (the services that may carry it).
++- **Only the person's own access token can produce one.** Network mints them at `POST /internal/subject-assertions`
++ (a first-party service token in `Authorization`, the person's own Network access token in `user_token`). Without
++ that token nothing is signed (401 `assertion.no_user_token`), so a service that merely knows a person's id cannot
++ say the person allowed anything. The signing key is Network's own EC (P-256) key, published in its JWKS beside the
++ RS256 session key (`kid ov-network-assertion-1`), so a receiver verifies the signature offline.
++- **Only a token Network issued for its own API mints one.** The service token must be for the audience
++ `openvibe.network`; one minted for another audience (a service talking to Billing, say) is refused (401
++ `token.wrong_audience`), so a service cannot reuse a token it holds elsewhere to have Network sign for people.
++- **The receiver checks the assertion against the person the route acts for.** A route that names a person
++ (`from`, `subject`, `subscriber`, `?subject=`, the path's `usr_…`) must carry the assertion in
++ `X-OV-Subject-Assertion`, and the assertion's `sub` must be that person. One that names another person is refused
++ (403 `subject.assertion_mismatch`) and no money moves.
++- **The audience is checked.** The assertion must be for the receiver's own service (`audience` includes
++ `openvibe.billing` / `openvibe.tips`); one minted for another service is refused (403
++ `assertion.wrong_audience`). A forged or malformed one is refused (403 `assertion.malformed` /
++ `assertion.bad_signature`), an expired one (403 `assertion.expired`), and a replayed one (403
++ `assertion.replayed`): the receiver remembers the `jti` for the replay window.
++- **The service presenting the assertion must be one the assertion names.** `act` is the service it was minted for;
++ `for` names the others that may carry it (a chain). A service that is not in it is refused (403
++ `assertion.actor_mismatch`) — another service's proof is not this service's proof.
++- **A chain carries one assertion.** When the assertion travels (the site mints it for Tips and Billing, Tips carries
++ it on to Billing), the audience is a list and `for` names the services allowed to carry it. The receiver still
++ checks the presenter against `for`.
++- **A person acting for themselves needs none.** A call with the person's own token is not a delegated call: the
++ person is the caller. Billing's own `/api/me/*` routes (the person's wallet) are in this shape.
++- **The switch is off first.** `BILLING_REQUIRE_SUBJECT_ASSERTION` / `TIPS_REQUIRE_SUBJECT_ASSERTION` (off) refuse the
++ old, vouched way once every caller sends assertions. While the flag is off a route that names a person still works
++ the old way, but an assertion that comes is always checked: one that names another person, or that belongs to
++ another service, is refused even with the flag off (money never moves for the wrong person), and one that does not
++ verify is counted and ignored. The receivers say what they saw on `/metrics`
++ (`billing_subject_assertion_calls` / `tips_subject_assertion_calls`, states `asserted`, `unasserted`, `invalid`,
++ `refused`): the flag turns on when `unasserted` stops moving, because that is the number that says every caller
++ sends assertions.
++- **Background work cannot carry one.** An assertion needs the person's live token, so a background path (a cache
++ refresh, a relay) cannot produce one. Those paths keep the old way until they hold the person's token; the flag
++ stays off for a service until every one of its per-person calls can carry one.
++
++### Who mints, who carries
++
++- **Network** signs (`POST /internal/subject-assertions`, the JWKS key, the limiter).
++- **The SDK** (`openvibe-sdk/assertions`) has the two halves: `requestSubjectAssertion()` for a caller,
++ `verifySubjectAssertion()` / `createSubjectAssertionVerifier()` for a receiver (JWKS cached, audience, expiry and
++ the `jti` replay window checked), and `createSubjectAssertionMinter()` for a caller's own helper.
++- **Billing and Tips** check (every per-person route; the flags above).
++- **The callers** mint and carry: Live (its money calls), Tips (the person tipping; and it carries the assertion on
++ to Billing), VIP (a membership bought from the member's credit), the Network wallet (the journal read with
++ Network's service token). A service that only reads a person's own wallet with that person's own token (Services)
++ needs none.
++
++### Tests
++
++- Network: minted with the person's token; refused without it (401); an app token is refused (403
++ `assertion.not_a_service`); a token for another audience is refused (401 `token.wrong_audience`); a token naming
++ another person is refused (403 `assertion.subject_mismatch`); an audience outside the allow-list is refused (403
++ `assertion.audience_not_allowed`); the chain (`for` + an audience list) works; the published JWK carries no private
++ half.
++- Billing and Tips: forged, expired, replayed, wrong-audience and wrong-person assertions are refused, and with the
++ flag on the old way is refused too (403 `subject.assertion_required`); a mismatch never moves money.
++- The SDK: a good assertion verifies; a forged, tampered, expired, replayed, wrong-audience, wrong-issuer,
++ `alg=none` or keyless assertion does not; a caller without the person's token gets nothing; the minter answers
++ null (never throws) when the assertion cannot be had.
++- The callers: a money call for a person carries that person's assertion; a call without the person's token travels
++ the old way; two calls get two assertions.
ddiff --git a/fixtures/identity.subject-assertion-claims/invalid/no-jti.json b/fixtures/identity.subject-assertion-claims/invalid/no-jti.json
nnew file mode 100644
iindex 00000000..69686004
---- /dev/null
++++ b/fixtures/identity.subject-assertion-claims/invalid/no-jti.json
@@@ -0,0 +1,10 @@
++{
++ "iss": "https://openvibe.network",
++ "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNA1",
++ "aud": [
++ "openvibe.billing"
++ ],
++ "act": "svc:live",
++ "iat": 1790000000,
++ "exp": 1790000060
++}
ddiff --git a/fixtures/identity.subject-assertion-claims/invalid/no-person.json b/fixtures/identity.subject-assertion-claims/invalid/no-person.json
nnew file mode 100644
iindex 00000000..9c77aa6f
---- /dev/null
++++ b/fixtures/identity.subject-assertion-claims/invalid/no-person.json
@@@ -0,0 +1,11 @@
++{
++ "iss": "https://openvibe.network",
++ "sub": "svc:live",
++ "aud": [
++ "openvibe.billing"
++ ],
++ "act": "svc:live",
++ "jti": "as_abcdef12",
++ "iat": 1790000000,
++ "exp": 1790000060
++}
ddiff --git a/fixtures/identity.subject-assertion-claims/invalid/other-audience.json b/fixtures/identity.subject-assertion-claims/invalid/other-audience.json
nnew file mode 100644
iindex 00000000..e36d9afd
---- /dev/null
++++ b/fixtures/identity.subject-assertion-claims/invalid/other-audience.json
@@@ -0,0 +1,11 @@
++{
++ "iss": "https://openvibe.network",
++ "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNA1",
++ "aud": [
++ "media"
++ ],
++ "act": "svc:live",
++ "jti": "as_abcdef12",
++ "iat": 1790000000,
++ "exp": 1790000060
++}
ddiff --git a/fixtures/identity.subject-assertion-claims/valid/chain-tip-to-billing.json b/fixtures/identity.subject-assertion-claims/valid/chain-tip-to-billing.json
nnew file mode 100644
iindex 00000000..ee477d82
---- /dev/null
++++ b/fixtures/identity.subject-assertion-claims/valid/chain-tip-to-billing.json
@@@ -0,0 +1,16 @@
++{
++ "iss": "https://openvibe.network",
++ "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNA1",
++ "aud": [
++ "openvibe.tips",
++ "openvibe.billing"
++ ],
++ "act": "svc:live",
++ "for": [
++ "svc:live",
++ "svc:tips"
++ ],
++ "jti": "as_abcdef13",
++ "iat": 1790000000,
++ "exp": 1790000060
++}
ddiff --git a/fixtures/identity.subject-assertion-claims/valid/live-to-billing.json b/fixtures/identity.subject-assertion-claims/valid/live-to-billing.json
nnew file mode 100644
iindex 00000000..0924779d
---- /dev/null
++++ b/fixtures/identity.subject-assertion-claims/valid/live-to-billing.json
@@@ -0,0 +1,11 @@
++{
++ "iss": "https://openvibe.network",
++ "sub": "usr_01JAB2C3D4E5F6G7H8J9K0MNA1",
++ "aud": [
++ "openvibe.billing"
++ ],
++ "act": "svc:live",
++ "jti": "as_abcdef12",
++ "iat": 1790000000,
++ "exp": 1790000060
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex b6893f52..437a1a75 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -362,6 +362,79 @@
]
}
},
++ "identity.subject-assertion-claims": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/identity/subject-assertion-claims.v1.json",
++ "title": "SubjectAssertionClaims",
++ "description": "Claims of a short-lived ES256 assertion signed by OpenVibe.Network that says a person allowed one service to act for them on another service (ADR-003, amendment 2026-11-06; plan H1). Minted only from the person's own Network access token (POST /internal/subject-assertions): without that token nothing is signed. Carried on a money call in X-OV-Subject-Assertion. The signature key is published in Network's JWKS (kid ov-network-assertion-1, kty EC, alg ES256) beside the RS256 session key, so a receiver verifies it offline.",
++ "type": "object",
++ "required": [
++ "iss",
++ "sub",
++ "aud",
++ "act",
++ "jti",
++ "iat",
++ "exp"
++ ],
++ "additionalProperties": true,
++ "properties": {
++ "iss": {
++ "type": "string",
++ "format": "uri",
++ "description": "Issuer; https://openvibe.network in production. The receiver checks it against the issuer it expects."
++ },
++ "sub": {
++ "type": "string",
++ "pattern": "^usr_[0-9A-HJKMNP-TV-Z]{26}$",
++ "description": "The person the assertion is about: their canonical subject. The receiver refuses an assertion that does not name the person the route acts for."
++ },
++ "aud": {
++ "type": "array",
++ "minItems": 1,
++ "items": {
++ "type": "string",
++ "pattern": "^openvibe\\.[a-z0-9][a-z0-9.-]*$"
++ },
++ "description": "The service(s) the assertion is for. A receiver accepts it only when its own audience is in the list. A list is used when the assertion travels a chain (a tip goes from the site to Tips and on to Billing)."
++ },
++ "act": {
++ "type": "string",
++ "pattern": "^svc:[a-z][a-z0-9-]{1,39}$",
++ "description": "The service the assertion was minted for (the one that held the person's token). It is the only service that may present it, unless `for` names others."
++ },
++ "for": {
++ "type": "array",
++ "items": {
++ "type": "string",
++ "pattern": "^svc:[a-z][a-z0-9-]{1,39}$"
++ },
++ "description": "The services that may carry the assertion (the minting service is always in it). A receiver presented by a service that is not in this list refuses the assertion (403 assertion.actor_mismatch)."
++ },
++ "jti": {
++ "type": "string",
++ "minLength": 8,
++ "description": "Unique per assertion. A receiver remembers the jtis it has seen for the replay window and refuses a second use (403 assertion.replayed)."
++ },
++ "iat": {
++ "type": "integer",
++ "description": "Issued at (seconds since the epoch)."
++ },
++ "exp": {
++ "type": "integer",
++ "description": "Expires at (seconds since the epoch). The assertion lives 60 seconds."
++ },
++ "nbf": {
++ "type": "integer",
++ "description": "Not before (seconds since the epoch). Optional; a receiver forgives a small clock difference."
++ }
++ }
++ }
++ },
"identity.realtime-ticket-claims": {
"version": "1.0.0",
"owner": "network",
ddiff --git a/generated/openapi/actor.json b/generated/openapi/actor.json
iindex 2de25466..6ae35261 100644
---- a/generated/openapi/actor.json
++++ b/generated/openapi/actor.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Actor API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex 8de4e155..71f5050a 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.296.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/bench.json b/generated/openapi/bench.json
iindex 783537ba..30a7e4d2 100644
---- a/generated/openapi/bench.json
++++ b/generated/openapi/bench.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bench API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 0a1ebdbd..97de053c 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.296.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 4e95e042..0582467c 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.296.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/bot.json b/generated/openapi/bot.json
iindex 92cbbc2b..c0d4ea44 100644
---- a/generated/openapi/bot.json
++++ b/generated/openapi/bot.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bot API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 c5950a1d..953b83a5 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.296.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 4fa2636f..f4ab9ab5 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.296.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 630a01c7..6668150c 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.296.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 77d36201..b0ae6be5 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.296.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 1b1a89ff..57263c03 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.296.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/domains.json b/generated/openapi/domains.json
iindex 75bdf79d..31b7b78c 100644
---- a/generated/openapi/domains.json
++++ b/generated/openapi/domains.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Domains API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 bc3653a2..23944d7d 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.296.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/food.json b/generated/openapi/food.json
iindex bd28e4db..4d44fc76 100644
---- a/generated/openapi/food.json
++++ b/generated/openapi/food.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Food API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 3cb84bf0..66141842 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.296.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 d9f9ad03..02563cf8 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.296.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/inventory.json b/generated/openapi/inventory.json
iindex f2d07905..ab34726f 100644
---- a/generated/openapi/inventory.json
++++ b/generated/openapi/inventory.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Inventory API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 2454e945..741be995 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.296.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/media-hub.json b/generated/openapi/media-hub.json
iindex e6ad57b2..083835bc 100644
---- a/generated/openapi/media-hub.json
++++ b/generated/openapi/media-hub.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.MediaHub API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 fca276f2..089f5739 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.296.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 02399112..66be468a 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.296.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 e2a70f85..83eece36 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.296.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 10ca7eb7..41025d63 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRestream API",
-- "version": "0.296.0",
-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/play.json b/generated/openapi/play.json
iindex d9670caf..eb35b97e 100644
---- a/generated/openapi/play.json
++++ b/generated/openapi/play.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Play API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/quest.json b/generated/openapi/quest.json
iindex 1e285337..ee6bcff4 100644
---- a/generated/openapi/quest.json
++++ b/generated/openapi/quest.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Quest API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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/report.json b/generated/openapi/report.json
iindex 0f56324c..f2677fde 100644
---- a/generated/openapi/report.json
++++ b/generated/openapi/report.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Report API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 abe7b659..0523d1fc 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.296.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/run.json b/generated/openapi/run.json
iindex 94c2e29d..75823904 100644
---- a/generated/openapi/run.json
++++ b/generated/openapi/run.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Run API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 bc4b5228..b79c46e3 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.296.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/services.json b/generated/openapi/services.json
iindex 38d48f36..03310aa5 100644
---- a/generated/openapi/services.json
++++ b/generated/openapi/services.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Services API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 55813825..83fb0ebd 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.296.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/space.json b/generated/openapi/space.json
iindex ee860779..b20cc0a2 100644
---- a/generated/openapi/space.json
++++ b/generated/openapi/space.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Space API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 7fcd13ed..76e78960 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.296.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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/today.json b/generated/openapi/today.json
iindex 7e13f6af..62d7a1d5 100644
---- a/generated/openapi/today.json
++++ b/generated/openapi/today.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Today API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 8fbab5c5..f2108924 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.296.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 4eb95aa9..54acf192 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.296.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 d83ccbc7..ed89b208 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.296.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/vision.json b/generated/openapi/vision.json
iindex 229f3575..8e383fbb 100644
---- a/generated/openapi/vision.json
++++ b/generated/openapi/vision.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Vision API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/watch.json b/generated/openapi/watch.json
iindex 314adcea..48023b22 100644
---- a/generated/openapi/watch.json
++++ b/generated/openapi/watch.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Watch API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 ae50dd67..507bf237 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.296.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/work.json b/generated/openapi/work.json
iindex f62fe9e8..7db0176a 100644
---- a/generated/openapi/work.json
++++ b/generated/openapi/work.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Work API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/zone.json b/generated/openapi/zone.json
iindex b8b9e042..9bbadb61 100644
---- a/generated/openapi/zone.json
++++ b/generated/openapi/zone.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Zone API",
-- "version": "0.296.0",
-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.296.0): each operation lists the capabilities it performs; a token for 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.297.0",
++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.297.0): each operation lists the capabilities it performs; a token for 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 3f02d5e2..e07b70bf 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -104,6 +104,52 @@ export type ServiceTokenClaims = {
[k: string]: unknown | undefined;
};
++/** [email protected] (owner: network) */
++/**
++ * Claims of a short-lived ES256 assertion signed by OpenVibe.Network that says a person allowed one service to act for them on another service (ADR-003, amendment 2026-11-06; plan H1). Minted only from the person's own Network access token (POST /internal/subject-assertions): without that token nothing is signed. Carried on a money call in X-OV-Subject-Assertion. The signature key is published in Network's JWKS (kid ov-network-assertion-1, kty EC, alg ES256) beside the RS256 session key, so a receiver verifies it offline.
++ */
++export interface SubjectAssertionClaims {
++ /**
++ * Issuer; https://openvibe.network in production. The receiver checks it against the issuer it expects.
++ */
++ iss: string;
++ /**
++ * The person the assertion is about: their canonical subject. The receiver refuses an assertion that does not name the person the route acts for.
++ */
++ sub: string;
++ /**
++ * The service(s) the assertion is for. A receiver accepts it only when its own audience is in the list. A list is used when the assertion travels a chain (a tip goes from the site to Tips and on to Billing).
++ *
++ * @minItems 1
++ */
++ aud: [string, ...string[]];
++ /**
++ * The service the assertion was minted for (the one that held the person's token). It is the only service that may present it, unless `for` names others.
++ */
++ act: string;
++ /**
++ * The services that may carry the assertion (the minting service is always in it). A receiver presented by a service that is not in this list refuses the assertion (403 assertion.actor_mismatch).
++ */
++ for?: string[];
++ /**
++ * Unique per assertion. A receiver remembers the jtis it has seen for the replay window and refuses a second use (403 assertion.replayed).
++ */
++ jti: string;
++ /**
++ * Issued at (seconds since the epoch).
++ */
++ iat: number;
++ /**
++ * Expires at (seconds since the epoch). The assertion lives 60 seconds.
++ */
++ exp: number;
++ /**
++ * Not before (seconds since the epoch). Optional; a receiver forgives a small clock difference.
++ */
++ nbf?: number;
++ [k: string]: unknown | undefined;
++}
++
/** [email protected] (owner: network) */
/**
* Claims of a realtime ticket (ADR-005 amendment 2; roadmap WS-E task 3, WS-F task 1): a two-minute RS256 JWT that OpenVibe.Network signs for the signed-in person (POST /api/v1/realtime/ticket) so a browser on any OpenVibe site can open Events' /realtime/stream?ticket=... as that person. A browser cannot put a header on an EventSource, and the ov_token cookie of openvibe.events is third-party on every other site, so the ticket travels in the URL; that is why it is short-lived, single-purpose and single-use. It is never a session token, by three independent rules: its issuer is Network's issuer followed by /realtime (every service checks the issuer of a session token), it carries typ (services refuse a session token that has one, as for FedCM assertions), and its only audience is openvibe.events. Events accepts it only as ?ticket= on /realtime/stream, verifies the signature with Network's key, iss, aud, typ, purpose and expiry (lifetime at most 300 s), refuses a jti it has already seen while the ticket is valid, and never logs it. The connection then sees what the person's session would: public events and subject events addressed to `sub`.
ddiff --git a/package-lock.json b/package-lock.json
iindex 449f44ab..b804b73a 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-contracts",
-- "version": "0.296.0",
++ "version": "0.297.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-contracts",
-- "version": "0.296.0",
++ "version": "0.297.0",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 21b3efa3..2e099d38 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.296.0",
++ "version": "0.297.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",