openvibers/openvibe.contracts Commits

Contracts 0.127.0: ai.openvibe.network and events.openvibe.network retired; service-auth drops the X-Internal-Key hook (#78)

OP OpenVibers committed 10 Oct 2026 · 5009f99c7e · 48 files, +96 −123

Contracts 0.127.0, retiring the old addresses (plan T6 "the ai.openvibe.network redirect removed once nothing calls it", T7 "events.openvibe.network is deleted after the move") and finishing T2's X-Internal-Key retirement in the library.

**Evidence that nothing calls them** (nginx access logs on the host, all rotations):
- `events.openvibe.network`: the last service call (a `node` client polling `/api/v1/events`) was 2026-09-30 18:25.
- `ai.openvibe.network`: the last service call (a `/release.json` poller from the host) was 2026-10-02 00:13.

Since then, only crawlers and the release UX check (until 09-30) have reached either address.

**Changes:**
- `ai.openvibe.network` / `events.openvibe.network` leave the `ai` and `events` service and repository manifests, and the `ai.openvibe.network` "moved" product manifest is deleted. The Sites-domains test snapshot drops it too (34 domains).
- Descriptions name only `ai.openvibe.services` and `openvibe.events`.
- The AI repository manifest no longer lists a domain the network doesn't hold. The AI service manifest no longer describes SQLite (AI is on PostgreSQL).
- `lib/service-auth.js`: `requireCapability` drops the `legacy` option (the X-Internal-Key hook). No consumer passes it; the test now asserts an X-Internal-Key alone opens nothing.

Generated files regenerated. `npm test`: 18,057 checks, compat vs v0.126.0 has no breaking changes. The old vhosts come out of the Events and AI repos and production in follow-up PRs.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex bb6a752b..0fca767d 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,17 @@ 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.127.0 — 2026-10-10
++
++- **Retired addresses leave the registry.** `ai.openvibe.network` and `events.openvibe.network` are no longer domains
++ of the `ai` and `events` services or of their repositories; their last service callers stopped on 2026-10-02 and
++ 2026-09-30, and only crawlers reached them since. The `ai.openvibe.network` "moved" product manifest is deleted, and
++ descriptions now name only `ai.openvibe.services` and `openvibe.events`. The AI repository manifest no longer lists a
++ domain the network does not hold. The AI service manifest no longer describes a SQLite database (AI runs on
++ PostgreSQL, ov_ai).
++- **`lib/service-auth.js`:** `requireCapability` drops the `legacy` option (the X-Internal-Key compatibility hook, plan
++ T2). Only a Bearer service token opens a route; no consumer passed it any more.
++
## 0.126.0 — 2026-10-09
- **OpenVibe Live on by default for OpenRestream.** New capability `live.openre.slot.bind` (active, internal):
ddiff --git a/STATUS.json b/STATUS.json
iindex 34871d74..d0311cac 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -9,7 +9,7 @@
"plan": "OpenVibe Development Roadmap (combined), Wave 1; implementation plan rev 3 section 3.1",
"deployed": false,
"deployment": "none of its own: a library and artifact repository published as release tags; services pin a tag and deploy it with their own releases",
-- "contracts": "openvibe-contracts v0.126.0 (this package; the newest tag)",
++ "contracts": "openvibe-contracts v0.127.0 (this package; the newest tag)",
"features": [
"589 JSON Schemas with valid and invalid fixtures",
"31 service manifests with lifecycle declarations",
ddiff --git a/contracts/identity/realtime-ticket-claims.v1.json b/contracts/identity/realtime-ticket-claims.v1.json
iindex 387733c2..b5179b15 100644
---- a/contracts/identity/realtime-ticket-claims.v1.json
++++ b/contracts/identity/realtime-ticket-claims.v1.json
@@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/identity/realtime-ticket-claims.v1.json",
"title": "RealtimeTicketClaims",
-- "description": "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 events.openvibe.network 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`.",
++ "description": "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`.",
"type": "object",
"required": [
"iss",
ddiff --git a/contracts/network/realtime-ticket-result.v1.json b/contracts/network/realtime-ticket-result.v1.json
iindex 02605165..6500acae 100644
---- a/contracts/network/realtime-ticket-result.v1.json
++++ b/contracts/network/realtime-ticket-result.v1.json
@@@ -34,7 +34,7 @@
"type": "string",
"format": "uri",
"pattern": "^https?://[^?#]+/realtime/stream$",
-- "description": "Events' realtime stream (https://openvibe.events/realtime/stream; https://events.openvibe.network/realtime/stream until every client has moved)."
++ "description": "Events' realtime stream (https://openvibe.events/realtime/stream)."
},
"topics": {
"type": "array",
ddiff --git a/docs/ESTATE.md b/docs/ESTATE.md
iindex 4a161bdd..dcefa92d 100644
---- a/docs/ESTATE.md
++++ b/docs/ESTATE.md
@@@ -13,7 +13,7 @@ service id); **Runtime** is `STATUS.json.runtime`; **Database** is inferred from
|---|---|---|---|---|---|---|---|---|---|
| AFResume | — | — | — | — | — | — | — | — | — |
| OpenRestream | OpenRestream | openre.* | node 22 | PostgreSQL | openre.stream, ingest.openre.stream | contracts v0.76.0, sdk v0.26.0, shared v2.10.1 | deployed | internal | W7 |
--| OpenVibe.AI | OpenVibe.AI | ai.usage_summary | node 22 | PostgreSQL | ai.openvibe.services, ai.openvibe.network, openvibe.ai | contracts v0.86.0, sdk v0.26.0, shared v2.5.0 | deployed | live | W13 |
++| OpenVibe.AI | OpenVibe.AI | ai.usage_summary | node 22 | PostgreSQL | ai.openvibe.services | contracts v0.86.0, sdk v0.26.0, shared v2.5.0 | deployed | live | W13 |
| OpenVibe.Billing | OpenVibe.Billing | billing.* | node >=22.0.0 | PostgreSQL | billing.openvibe.network | contracts v0.97.0, sdk v0.28.0, shared v2.9.0 | deployed | live | W8 |
| OpenVibe.Blog | Blog | blog.* | node 22 | PostgreSQL | openvibe.blog | contracts v0.97.0, sdk v0.26.0, shared v2.9.0, publishing v1.3.0 | deployed | live | W16 |
| OpenVibe.Bot | Bot | bot | node 22 | PostgreSQL | openvibe.bot | contracts v0.96.0, sdk v0.26.0, shared v2.10.1 | deployed | live | — |
@@@ -23,7 +23,7 @@ service id); **Runtime** is `STATUS.json.runtime`; **Database** is inferred from
| OpenVibe.Contracts | OpenVibe.Contracts | contracts | node >=20 | — | — | contracts v0.106.0 | not deployed | library | W1 |
| OpenVibe.Coupons | Coupons | coupons.* | node 22 | PostgreSQL | openvibe.coupons | contracts v0.97.0, sdk v0.26.0, shared v2.9.0, publishing v1.3.0 | deployed | internal | W18 |
| OpenVibe.Deals | Deals | deals.* | node 22 | PostgreSQL | openvibe.deals | contracts v0.97.0, sdk v0.26.0, shared v2.10.1, publishing v1.3.0 | deployed | internal | W18 |
--| OpenVibe.Events | OpenVibe.Events | events | node 22 | PostgreSQL | openvibe.events, events.openvibe.network | contracts v0.94.2, sdk v0.26.0, shared v2.10.1 | deployed | live | W3 |
++| OpenVibe.Events | OpenVibe.Events | events | node 22 | PostgreSQL | openvibe.events | contracts v0.94.2, sdk v0.26.0, shared v2.10.1 | deployed | live | W3 |
| OpenVibe.Examples | OpenVibe.Examples | examples | node >=22 | — | — | contracts v0.49.0, sdk v0.11.0 | not deployed | repository | W20 |
| OpenVibe.Extensions | — | — | node >=22.0.0 | — | — | — | not deployed | — | W18 |
| OpenVibe.Games | Games | games.* | node 22 | PostgreSQL | openvibe.games, play.openvibe.games | contracts v0.78.0, sdk v0.23.1, shared v2.6.0 | deployed | live | — |
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex d599dc92..ae947820 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -370,7 +370,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://openvibe.network/contracts/identity/realtime-ticket-claims.v1.json",
"title": "RealtimeTicketClaims",
-- "description": "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 events.openvibe.network 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`.",
++ "description": "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`.",
"type": "object",
"required": [
"iss",
@@@ -29029,7 +29029,7 @@
"type": "string",
"format": "uri",
"pattern": "^https?://[^?#]+/realtime/stream$",
-- "description": "Events' realtime stream (https://openvibe.events/realtime/stream; https://events.openvibe.network/realtime/stream until every client has moved)."
++ "description": "Events' realtime stream (https://openvibe.events/realtime/stream)."
},
"topics": {
"type": "array",
ddiff --git a/generated/openapi/actor.json b/generated/openapi/actor.json
iindex 0891007e..aed27eb6 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.126.0",
-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 5fb9e3b1..e7b40c63 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.126.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 4d84b422..7d6f77ab 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.126.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 0b0d729f..3f4b083f 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.126.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 15bec0b3..da9bf24a 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.126.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 a245061e..7e7ecc3a 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.126.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 945a339f..796f699e 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.126.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 ac53654d..5b561be0 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.126.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 69c7b869..85c5f8a7 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.126.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 a710496f..d2370ef8 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.126.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 61e4b729..1cd08b59 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.126.0",
-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 67241955..921e9561 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.126.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 286904b8..5bae6b61 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.126.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 8d7c9f3e..cf97e762 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.126.0",
-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 9076e113..751c4543 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.126.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 fee11aeb..5c311685 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.126.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 84da1c19..cb87dd00 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.126.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 47d30e32..c58217c1 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.126.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 0f8a390e..af2a13e2 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.126.0",
-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 6b2f285d..73550753 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.126.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 9357cea2..2f135229 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.126.0",
-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 dcdbe190..d3514ef7 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.126.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 d05ae1a9..b04494b7 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.126.0",
-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 02b89183..4d48c286 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.126.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 fd8c5d2b..240b46fc 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.126.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 b5b4c9a8..a6d3e65e 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.126.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 a9bbd4e1..a8942db1 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.126.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 dae3eac4..20713826 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.126.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 4802e21a..6c974674 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.126.0",
-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 8430c648..50123c2e 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.126.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.126.0): each operation lists the capabilities it performs; a token for 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.127.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.127.0): each operation lists the capabilities it performs; a token for 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 da12f7c6..0ac6de48 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -106,7 +106,7 @@ export type ServiceTokenClaims = {
/** [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 events.openvibe.network 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`.
++ * 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`.
*/
export interface RealtimeTicketClaims {
/**
@@@ -33394,7 +33394,7 @@ export interface NetworkRealtimeTicketResult {
*/
expires_in: number;
/**
-- * Events' realtime stream (https://openvibe.events/realtime/stream; https://events.openvibe.network/realtime/stream until every client has moved).
++ * Events' realtime stream (https://openvibe.events/realtime/stream).
*/
stream_url: string;
/**
ddiff --git a/lib/service-auth.js b/lib/service-auth.js
iindex 321d1cec..ab361836 100644
---- a/lib/service-auth.js
++++ b/lib/service-auth.js
@@@ -56,10 +56,8 @@ function verifyServiceToken(token, { publicKey, issuer, audience, clockSkewSec =
* Express guard: `router.post('/coins/credit', requireCapability('network.coins.credit', opts), handler)`.
* opts.publicKey | opts.getPublicKey(req), opts.issuer, opts.audience
* opts.namespace(req) -> namespace to check against the token's `ns` (optional)
-- * opts.legacy(req) -> true when the request authenticated the old way (X-Internal-Key); it is let
-- * through as `req.principal = { legacy: true }` so both work during migration.
* opts.onDecision({ req, capability, principal, allowed, code }) -> audit hook
-- * A request that presents a Bearer token is judged ONLY on that token, never on a legacy header.
++ * Only a Bearer service token opens the route (the X-Internal-Key path is retired, plan T2).
*/
function requireCapability(capability, opts = {}) {
if (!capabilities.get(capability)) throw new Error(`requireCapability: unknown capability ${capability}`);
@@@ -80,7 +78,6 @@ function requireCapability(capability, opts = {}) {
const c = capabilities.check(r.claims, capability, { namespace: ns });
return decide(c.allowed, c.code, { sub: r.claims.sub, cap: r.claims.cap, ns: r.claims.ns, jti: r.claims.jti }, c.reason);
}
-- if (opts.legacy && opts.legacy(req)) return decide(true, null, { legacy: true });
return decide(false, 'capability.denied', null, 'no service token');
};
}
ddiff --git a/manifests/products/ai.openvibe.network.json b/manifests/products/ai.openvibe.network.json
ddeleted file mode 100644
iindex a7342205..00000000
---- a/manifests/products/ai.openvibe.network.json
++++ /dev/null
@@@ -1,29 +0,0 @@
--{
-- "domain": "ai.openvibe.network",
-- "tld": "ai",
-- "name": "ai.openvibe.network",
-- "icon": "fa-robot",
-- "accent": "#c084fc",
-- "tagline": "Moved: OpenVibe.AI's public home is ai.openvibe.services.",
-- "legalProfile": "info",
-- "kind": "moved",
-- "description": "OpenVibe.AI's public address is now ai.openvibe.services, next to the rest of the network's programmable services on OpenVibe.Services. This address serves only this notice until every client has moved; then it redirects.",
-- "keywords": "openvibe ai, openvibe network ai, openvibe platform",
-- "relationships": {
-- "service": "ai",
-- "plannedRepo": "OpenVibe.AI",
-- "linksLead": "OpenVibe.AI lives on OpenVibe.Services now.",
-- "links": [
-- {
-- "label": "ai.openvibe.services",
-- "url": "https://ai.openvibe.services/",
-- "note": "OpenVibe.AI: the gateway, templates, workflows and runs."
-- },
-- {
-- "label": "OpenVibe.Services",
-- "url": "https://openvibe.services/",
-- "note": "Every programmable OpenVibe service in one place."
-- }
-- ]
-- }
--}
ddiff --git a/manifests/products/realtime.openvibe.network.json b/manifests/products/realtime.openvibe.network.json
iindex 70a1e4ca..76091c63 100644
---- a/manifests/products/realtime.openvibe.network.json
++++ b/manifests/products/realtime.openvibe.network.json
@@@ -7,7 +7,7 @@
"tagline": "Closed: realtime delivery is part of OpenVibe.Events.",
"legalProfile": "info",
"kind": "closed",
-- "description": "OpenVibe.Realtime was planned as a separate service for live updates in the browser. Decision record ADR-005 (accepted 2026-09-22) closed it: browser realtime is part of OpenVibe.Events, as server-sent events with cursor resume at events.openvibe.network/realtime/stream. This address serves only this notice.",
++ "description": "OpenVibe.Realtime was planned as a separate service for live updates in the browser. Decision record ADR-005 (accepted 2026-09-22) closed it: browser realtime is part of OpenVibe.Events, as server-sent events with cursor resume at openvibe.events/realtime/stream. This address serves only this notice.",
"keywords": "openvibe realtime, openvibe events, server-sent events",
"relationships": {
"noRepo": true,
ddiff --git a/manifests/repositories/OpenVibe.AI.json b/manifests/repositories/OpenVibe.AI.json
iindex acf26505..40d0aa40 100644
---- a/manifests/repositories/OpenVibe.AI.json
++++ b/manifests/repositories/OpenVibe.AI.json
@@@ -12,9 +12,7 @@
"ai.usage_summary"
],
"domains": [
-- "ai.openvibe.services",
-- "ai.openvibe.network",
-- "openvibe.ai"
++ "ai.openvibe.services"
],
"pins": {
"openvibe-contracts": "v0.86.0",
ddiff --git a/manifests/repositories/OpenVibe.Events.json b/manifests/repositories/OpenVibe.Events.json
iindex 30c99ba5..654c711d 100644
---- a/manifests/repositories/OpenVibe.Events.json
++++ b/manifests/repositories/OpenVibe.Events.json
@@@ -12,8 +12,7 @@
"events"
],
"domains": [
-- "openvibe.events",
-- "events.openvibe.network"
++ "openvibe.events"
],
"pins": {
"openvibe-contracts": "v0.94.2",
ddiff --git a/manifests/services/ai.json b/manifests/services/ai.json
iindex 2ae36ae1..0f8686a5 100644
---- a/manifests/services/ai.json
++++ b/manifests/services/ai.json
@@@ -8,8 +8,7 @@
"status": "alpha",
"repository": "OpenVibers/OpenVibe.AI",
"domains": [
-- "ai.openvibe.services",
-- "ai.openvibe.network"
++ "ai.openvibe.services"
],
"publicOrigin": "https://ai.openvibe.services",
"health": "/api/health",
@@@ -18,7 +17,7 @@
"exposure": {
"state": "live",
"publicSite": "service",
-- "note": "the public home, /stats and the developer-app API (ai.app.run) at ai.openvibe.services since 2026-10-07 (AI #23); ai.openvibe.network answers 301 to it; services on the host call 127.0.0.1:4700"
++ "note": "the public home, /stats and the developer-app API (ai.app.run) at ai.openvibe.services since 2026-10-07 (AI #23); the old ai.openvibe.network address was retired on 2026-10-10; services on the host call 127.0.0.1:4700"
},
"capabilities": [
"ai.app.run",
@@@ -77,14 +76,14 @@
],
"window": "automatic only while ovhost waits for readiness after the restart (30 s in host.example.json); manual afterwards, as long as no blocker applies",
"blockers": {
-- "none": "the schema code only adds (CREATE \u2026 IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"
++ "none": "the schema code only adds (CREATE … IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"
}
},
"contracts": {
"range": ">=0.6.0 <1.0.0"
},
"leases": {
-- "none": "no claims: one process owns ai.db (better-sqlite3, single writer); a run is taken with a compare-and-set on its status (queued \u2192 running)"
++ "none": "no claims: one process owns its PostgreSQL database (ov_ai); a run is taken with a compare-and-set on its status (queued → running)"
}
},
"notes": "Providers, models, routing profiles, versioned prompt templates and workflows, runs, request logs, citations, scoped cache, quotas and audit. Workflow output is a draft/evidence package attributed to workflow + model + run. ai.run.queued|succeeded|failed|cached have payload contracts (v0.30.0, status planned): AI publishes them once its Events client is wired in; it publishes none today. ai.run.create takes ai.run-request@1 and returns ai.run@1."
ddiff --git a/manifests/services/events.json b/manifests/services/events.json
iindex 260eee41..075b2b38 100644
---- a/manifests/services/events.json
++++ b/manifests/services/events.json
@@@ -8,8 +8,7 @@
"status": "alpha",
"repository": "OpenVibers/OpenVibe.Events",
"domains": [
-- "openvibe.events",
-- "events.openvibe.network"
++ "openvibe.events"
],
"publicOrigin": "https://openvibe.events",
"health": "/api/health",
@@@ -70,7 +69,7 @@
],
"window": "automatic only while ovhost waits for readiness after the restart (30 s in host.example.json); manual afterwards, as long as no blocker applies",
"blockers": {
-- "none": "the schema code only adds (CREATE \u2026 IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"
++ "none": "the schema code only adds (CREATE … IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"
}
},
"contracts": {
ddiff --git a/package.json b/package.json
iindex 1aa188d2..774ccec9 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.126.0",
++ "version": "0.127.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
ddiff --git a/test/fixtures/sites-domains.json b/test/fixtures/sites-domains.json
iindex 74d964fe..f7286905 100644
---- a/test/fixtures/sites-domains.json
++++ b/test/fixtures/sites-domains.json
@@@ -16,7 +16,6 @@
"admin.openvibe.network",
"themes.openvibe.network",
"realtime.openvibe.network",
-- "ai.openvibe.network",
"ai.openvibe.services",
"status.openvibe.network",
"openvibe.pics",
ddiff --git a/test/product-catalog.test.js b/test/product-catalog.test.js
iindex 291799ac..40712733 100644
---- a/test/product-catalog.test.js
++++ b/test/product-catalog.test.js
@@@ -29,7 +29,7 @@ for (const row of products.catalog()) homes.set(row.domain, [...(homes.get(row.d
for (const [domain, list] of homes) ok(list.length === 1, `${domain} has one home, not ${list.join(', ')}`);
const snapshot = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures/sites-domains.json'), 'utf8')).domains;
--ok(snapshot.length === 35 && new Set(snapshot).size === 35, 'the Sites snapshot holds 35 distinct domains');
++ok(snapshot.length === 34 && new Set(snapshot).size === 34, 'the Sites snapshot holds 34 distinct domains (ai.openvibe.network retired 2026-10-10)');
for (const d of snapshot) ok((homes.get(d) || []).length === 1, `${d} (OpenVibe.Sites) has exactly one Contracts home: ${(homes.get(d) || ['none']).join(', ')}`);
for (const p of products.manifests) {
ddiff --git a/test/run.js b/test/run.js
iindex 04e42cec..21e7ada2 100644
---- a/test/run.js
++++ b/test/run.js
@@@ -618,20 +618,20 @@ const run = (guard, headers) => new Promise((resolve) => {
guard(req, res, () => resolve({ status: 200, req }));
});
const audit = [];
--const opts = { publicKey: kp.publicKey, issuer: 'https://openvibe.network', audience: 'openvibe.network', legacy: (req) => req.headers['x-internal-key'] === 'k', onDecision: (d) => audit.push(d) };
++const opts = { publicKey: kp.publicKey, issuer: 'https://openvibe.network', audience: 'openvibe.network', onDecision: (d) => audit.push(d) };
let r = await run(serviceAuth.requireCapability('network.coins.credit', opts), { authorization: `Bearer ${tok}` });
ok(r.status === 200 && r.req.principal.sub === 'svc:live', 'granted capability passes with the principal attached');
r = await run(serviceAuth.requireCapability('network.coins.debit', opts), { authorization: `Bearer ${tok}` });
ok(r.status === 403 && r.body.code === 'capability.denied' && contracts.validate('errors.problem', r.body).valid, 'ungranted capability is a 403 problem');
r = await run(serviceAuth.requireCapability('network.coins.credit', opts), { authorization: 'Bearer garbage', 'x-internal-key': 'k' });
--ok(r.status === 401 && r.body.code === 'token.malformed', 'a bad token is not rescued by a legacy key');
++ok(r.status === 401 && r.body.code === 'token.malformed', 'a bad token is not rescued by an old X-Internal-Key');
r = await run(serviceAuth.requireCapability('network.coins.credit', opts), { 'x-internal-key': 'k' });
--ok(r.status === 200 && r.req.principal.legacy === true, 'legacy key still works in compatibility mode');
++ok(r.status === 403 && r.body.code === 'capability.denied', 'an X-Internal-Key alone opens nothing (retired, plan T2)');
r = await run(serviceAuth.requireCapability('network.coins.credit', opts), {});
ok(r.status === 403, 'no credentials, no access');
r = await run(serviceAuth.requireCapability('media.object.upload', { ...opts, audience: 'openvibe.network', namespace: () => 'games.maps' }), { authorization: `Bearer ${serviceAuth.signServiceToken({ ...claims, cap: ['media.object.*'], ns: ['live.*'] }, kp.privateKey)}` });
ok(r.status === 403 && r.body.code === 'capability.namespace_denied', 'namespace constraint enforced');
--ok(audit.length === 6 && audit.filter(a => a.allowed).length === 2, 'every decision reaches the audit hook');
++ok(audit.length === 6 && audit.filter(a => a.allowed).length === 1, 'every decision reaches the audit hook');
assert.throws(() => serviceAuth.requireCapability('nope.nope.nope'), /unknown capability/);
let calls = 0;