openvibers/openvibe.contracts Commits

v0.62.0: operator alerts (roadmap WS-H task 11). Capability network.operator.alert (internal; POST /internal/operator/alerts on Network, granted to the Host principal) with network.operator-alerts-request@1 (the complete set of alerts firing at one source: fingerprint, name, severity, summary, description, service, started_at) and network.operator-alerts-result@1 (firing, opened, reminded, resolved, notified). Network pages the owner when an alert opens, once a day while it stays open, and when it resolves.

OP OpenVibers committed 26 Sept 2026 · 24c51f2374 · 45 files, +490 −51


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 0b6a66ab..df14e649 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -6,6 +6,12 @@ the notes were in the tag and commit messages (`git tag -n1`).
## Unreleased
++## 0.62.0 — 2026-09-26
++
++**Operator alerts** (roadmap WS-H task 11; the delivery path that Host's Prometheus alerts lacked).
++- **New capability `network.operator.alert`** (internal, owner network), implemented by `POST /internal/operator/alerts` on OpenVibe.Network and granted to the Host principal. The request is the complete set of alerts firing now at one source (`prometheus`). Network pages the operator (the owner account) as a critical or high `admin` notification when an alert opens, reminds once a day while it stays open, and sends a resolved notice when it drops out of the set. Being an `admin` notification, it reaches the bell, web push and the realtime topic, and no block hides it.
++- **New schemas** `network.operator-alerts-request@1` (source, sent_at, up to 200 alerts: fingerprint, name, severity, summary, description, service, started_at; no free-form labels) and `network.operator-alerts-result@1` (firing, opened, reminded, resolved, notified).
++
## 0.61.0 — 2026-09-26
**A person's realtime topic and realtime tickets** (roadmap WS-E task 3, WS-F task 1; ADR-005 amendment 2).
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex 27191d99..f8bebe4c 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -2485,6 +2485,24 @@
"compatibility": "backward",
"status": "active"
},
++ {
++ "id": "network.operator-alerts-request",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "network/operator-alerts-request.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
++ {
++ "id": "network.operator-alerts-result",
++ "version": "1.0.0",
++ "owner": "network",
++ "schema": "network/operator-alerts-result.v1.json",
++ "visibility": "first-party",
++ "compatibility": "backward",
++ "status": "active"
++ },
{
"id": "network.realtime-ticket-result",
"version": "1.0.0",
ddiff --git a/contracts/network/operator-alerts-request.v1.json b/contracts/network/operator-alerts-request.v1.json
nnew file mode 100644
iindex 00000000..445eedad
---- /dev/null
++++ b/contracts/network/operator-alerts-request.v1.json
@@@ -0,0 +1,31 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/operator-alerts-request.v1.json",
++ "title": "NetworkOperatorAlertsRequest",
++ "description": "network.operator-alerts-request@1: POST /internal/operator/alerts on OpenVibe.Network (capability network.operator.alert, held by the Host principal). The complete set of alerts firing now at one source: an alert Network has not seen firing opens and pages the operator; one still firing is reminded once a day; one that was firing and is absent from the set is resolved and says so. An empty list resolves everything from that source. Fingerprints are stable per alert (name and labels), never secrets; summaries and descriptions are the alert rule's annotations.",
++ "type": "object",
++ "required": ["source", "alerts"],
++ "additionalProperties": false,
++ "properties": {
++ "source": { "enum": ["prometheus"], "description": "Where the alerts are evaluated. Resolution is per source." },
++ "sent_at": { "type": "string", "format": "date-time" },
++ "alerts": {
++ "type": "array",
++ "maxItems": 200,
++ "items": {
++ "type": "object",
++ "required": ["fingerprint", "name", "severity", "summary", "started_at"],
++ "additionalProperties": false,
++ "properties": {
++ "fingerprint": { "type": "string", "pattern": "^[0-9a-f]{16,64}$" },
++ "name": { "type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_:]{0,99}$" },
++ "severity": { "enum": ["critical", "warning", "info"] },
++ "summary": { "type": "string", "minLength": 1, "maxLength": 300 },
++ "description": { "type": "string", "maxLength": 1000 },
++ "service": { "type": "string", "pattern": "^[a-z][a-z0-9-]{1,39}$" },
++ "started_at": { "type": "string", "format": "date-time" }
++ }
++ }
++ }
++ }
++}
ddiff --git a/contracts/network/operator-alerts-result.v1.json b/contracts/network/operator-alerts-result.v1.json
nnew file mode 100644
iindex 00000000..8c69f72d
---- /dev/null
++++ b/contracts/network/operator-alerts-result.v1.json
@@@ -0,0 +1,17 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/operator-alerts-result.v1.json",
++ "title": "NetworkOperatorAlertsResult",
++ "description": "network.operator-alerts-result@1: the answer of POST /internal/operator/alerts. firing: alerts firing after this report; opened: newly firing (paged); reminded: still firing and paged again (once a day); resolved: no longer firing (a resolved notice sent); notified: notifications created across all recipients (0 when no operator account is found or they switched admin notices off). Errors are { error } bodies (400 for a body that breaks the request contract).",
++ "type": "object",
++ "required": ["ok", "firing", "opened", "reminded", "resolved", "notified"],
++ "additionalProperties": false,
++ "properties": {
++ "ok": { "const": true },
++ "firing": { "type": "integer", "minimum": 0 },
++ "opened": { "type": "integer", "minimum": 0 },
++ "reminded": { "type": "integer", "minimum": 0 },
++ "resolved": { "type": "integer", "minimum": 0 },
++ "notified": { "type": "integer", "minimum": 0 }
++ }
++}
ddiff --git a/fixtures/network.operator-alerts-request/invalid/extra-labels.json b/fixtures/network.operator-alerts-request/invalid/extra-labels.json
nnew file mode 100644
iindex 00000000..00345d39
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/invalid/extra-labels.json
@@@ -0,0 +1 @@
++{ "source": "prometheus", "alerts": [ { "fingerprint": "3f1c2a9b7d4e6f80", "name": "OpenVibeBackupMissed", "severity": "critical", "summary": "No backup", "started_at": "2026-09-26T05:35:00Z", "labels": { "instance": "127.0.0.1:9100" } } ] }
ddiff --git a/fixtures/network.operator-alerts-request/invalid/no-summary.json b/fixtures/network.operator-alerts-request/invalid/no-summary.json
nnew file mode 100644
iindex 00000000..2f3a58f0
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/invalid/no-summary.json
@@@ -0,0 +1 @@
++{ "source": "prometheus", "alerts": [ { "fingerprint": "3f1c2a9b7d4e6f80", "name": "OpenVibeBackupMissed", "severity": "critical", "started_at": "2026-09-26T05:35:00Z" } ] }
ddiff --git a/fixtures/network.operator-alerts-request/invalid/unknown-severity.json b/fixtures/network.operator-alerts-request/invalid/unknown-severity.json
nnew file mode 100644
iindex 00000000..cc7a6d1a
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/invalid/unknown-severity.json
@@@ -0,0 +1 @@
++{ "source": "prometheus", "alerts": [ { "fingerprint": "3f1c2a9b7d4e6f80", "name": "OpenVibeBackupMissed", "severity": "page", "summary": "No backup", "started_at": "2026-09-26T05:35:00Z" } ] }
ddiff --git a/fixtures/network.operator-alerts-request/invalid/unknown-source.json b/fixtures/network.operator-alerts-request/invalid/unknown-source.json
nnew file mode 100644
iindex 00000000..e448dc61
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/invalid/unknown-source.json
@@@ -0,0 +1 @@
++{ "source": "grafana", "alerts": [] }
ddiff --git a/fixtures/network.operator-alerts-request/invalid/uppercase-fingerprint.json b/fixtures/network.operator-alerts-request/invalid/uppercase-fingerprint.json
nnew file mode 100644
iindex 00000000..6b388772
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/invalid/uppercase-fingerprint.json
@@@ -0,0 +1 @@
++{ "source": "prometheus", "alerts": [ { "fingerprint": "3F1C2A9B7D4E6F80", "name": "OpenVibeBackupMissed", "severity": "critical", "summary": "No backup", "started_at": "2026-09-26T05:35:00Z" } ] }
ddiff --git a/fixtures/network.operator-alerts-request/valid/all-clear.json b/fixtures/network.operator-alerts-request/valid/all-clear.json
nnew file mode 100644
iindex 00000000..e06a74d7
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/valid/all-clear.json
@@@ -0,0 +1 @@
++{ "source": "prometheus", "alerts": [] }
ddiff --git a/fixtures/network.operator-alerts-request/valid/two-firing.json b/fixtures/network.operator-alerts-request/valid/two-firing.json
nnew file mode 100644
iindex 00000000..03cfeb1f
---- /dev/null
++++ b/fixtures/network.operator-alerts-request/valid/two-firing.json
@@@ -0,0 +1,8 @@
++{
++ "source": "prometheus",
++ "sent_at": "2026-09-26T14:10:00Z",
++ "alerts": [
++ { "fingerprint": "3f1c2a9b7d4e6f80", "name": "OpenVibeBackupMissed", "severity": "critical", "summary": "No successful backup in 26 hours", "description": "ovhost backup --all has not succeeded since 2026-09-25 03:35 UTC.", "service": "host", "started_at": "2026-09-26T05:35:00Z" },
++ { "fingerprint": "9a8b7c6d5e4f3a2b1c0d", "name": "OpenVibeBrowserCheckFailed", "severity": "warning", "summary": "The browser check of live failed after release 8caa540", "service": "live", "started_at": "2026-09-26T14:05:00Z" }
++ ]
++}
ddiff --git a/fixtures/network.operator-alerts-result/invalid/negative.json b/fixtures/network.operator-alerts-result/invalid/negative.json
nnew file mode 100644
iindex 00000000..21c73dea
---- /dev/null
++++ b/fixtures/network.operator-alerts-result/invalid/negative.json
@@@ -0,0 +1 @@
++{ "ok": true, "firing": -1, "opened": 0, "reminded": 0, "resolved": 0, "notified": 0 }
ddiff --git a/fixtures/network.operator-alerts-result/invalid/no-notified.json b/fixtures/network.operator-alerts-result/invalid/no-notified.json
nnew file mode 100644
iindex 00000000..8b21fb0c
---- /dev/null
++++ b/fixtures/network.operator-alerts-result/invalid/no-notified.json
@@@ -0,0 +1 @@
++{ "ok": true, "firing": 1, "opened": 1, "reminded": 0, "resolved": 0 }
ddiff --git a/fixtures/network.operator-alerts-result/valid/opened-and-resolved.json b/fixtures/network.operator-alerts-result/valid/opened-and-resolved.json
nnew file mode 100644
iindex 00000000..6bbe46e9
---- /dev/null
++++ b/fixtures/network.operator-alerts-result/valid/opened-and-resolved.json
@@@ -0,0 +1 @@
++{ "ok": true, "firing": 2, "opened": 1, "reminded": 0, "resolved": 1, "notified": 2 }
ddiff --git a/fixtures/network.operator-alerts-result/valid/quiet.json b/fixtures/network.operator-alerts-result/valid/quiet.json
nnew file mode 100644
iindex 00000000..999df1cc
---- /dev/null
++++ b/fixtures/network.operator-alerts-result/valid/quiet.json
@@@ -0,0 +1 @@
++{ "ok": true, "firing": 0, "opened": 0, "reminded": 0, "resolved": 0, "notified": 0 }
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex 59f97a74..54bb6e74 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -26010,6 +26010,130 @@
]
}
},
++ "network.operator-alerts-request": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/operator-alerts-request.v1.json",
++ "title": "NetworkOperatorAlertsRequest",
++ "description": "network.operator-alerts-request@1: POST /internal/operator/alerts on OpenVibe.Network (capability network.operator.alert, held by the Host principal). The complete set of alerts firing now at one source: an alert Network has not seen firing opens and pages the operator; one still firing is reminded once a day; one that was firing and is absent from the set is resolved and says so. An empty list resolves everything from that source. Fingerprints are stable per alert (name and labels), never secrets; summaries and descriptions are the alert rule's annotations.",
++ "type": "object",
++ "required": [
++ "source",
++ "alerts"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "source": {
++ "enum": [
++ "prometheus"
++ ],
++ "description": "Where the alerts are evaluated. Resolution is per source."
++ },
++ "sent_at": {
++ "type": "string",
++ "format": "date-time"
++ },
++ "alerts": {
++ "type": "array",
++ "maxItems": 200,
++ "items": {
++ "type": "object",
++ "required": [
++ "fingerprint",
++ "name",
++ "severity",
++ "summary",
++ "started_at"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "fingerprint": {
++ "type": "string",
++ "pattern": "^[0-9a-f]{16,64}$"
++ },
++ "name": {
++ "type": "string",
++ "pattern": "^[A-Za-z][A-Za-z0-9_:]{0,99}$"
++ },
++ "severity": {
++ "enum": [
++ "critical",
++ "warning",
++ "info"
++ ]
++ },
++ "summary": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 300
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 1000
++ },
++ "service": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,39}$"
++ },
++ "started_at": {
++ "type": "string",
++ "format": "date-time"
++ }
++ }
++ }
++ }
++ }
++ }
++ },
++ "network.operator-alerts-result": {
++ "version": "1.0.0",
++ "owner": "network",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/network/operator-alerts-result.v1.json",
++ "title": "NetworkOperatorAlertsResult",
++ "description": "network.operator-alerts-result@1: the answer of POST /internal/operator/alerts. firing: alerts firing after this report; opened: newly firing (paged); reminded: still firing and paged again (once a day); resolved: no longer firing (a resolved notice sent); notified: notifications created across all recipients (0 when no operator account is found or they switched admin notices off). Errors are { error } bodies (400 for a body that breaks the request contract).",
++ "type": "object",
++ "required": [
++ "ok",
++ "firing",
++ "opened",
++ "reminded",
++ "resolved",
++ "notified"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "firing": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "opened": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "reminded": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "resolved": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "notified": {
++ "type": "integer",
++ "minimum": 0
++ }
++ }
++ }
++ },
"network.realtime-ticket-result": {
"version": "1.0.0",
"owner": "network",
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex 63a77475..6ac8bb49 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.61.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 9d2736ce..990a5c47 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.61.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 3e1802ab..89fd99eb 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.61.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 fe56be07..7303139b 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.61.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 16f72c80..b3f8663e 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.61.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 01fec503..d37d5306 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.61.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 ba3f3c36..c73a0792 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.61.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 c85a1553..f60d3b27 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.61.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 161da6ee..934bfee6 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.61.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 1ddf2537..ff2ba018 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.61.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 c3c5c0e0..fab3b870 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.61.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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/index.json b/generated/openapi/index.json
iindex b860e2d2..e2d8ae06 100644
---- a/generated/openapi/index.json
++++ b/generated/openapi/index.json
@@@ -96,8 +96,8 @@
"service": "network",
"name": "OpenVibe.Network",
"origin": "https://openvibe.network",
-- "operations": 11,
-- "capabilities": 10
++ "operations": 12,
++ "capabilities": 11
},
{
"service": "news",
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex cfd2e3e3..6caf719f 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.61.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 103af38f..fcf6903e 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.61.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 fcc80701..b286281e 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.61.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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"
@@@ -618,6 +618,62 @@
}
}
}
++ },
++ "/internal/operator/alerts": {
++ "post": {
++ "operationId": "post_internal_operator_alerts",
++ "summary": "Report the complete set of alerts firing on the production host, so Network pages the operator (the owner account) when an alert opens, once a day while it stays open, and when it resolves.",
++ "description": "**network.operator.alert** (internal): Report the complete set of alerts firing on the production host, so Network pages the operator (the owner account) when an alert opens, once a day while it stays open, and when it resolves.",
++ "tags": [
++ "network.operator"
++ ],
++ "x-openvibe-capabilities": [
++ "network.operator.alert"
++ ],
++ "x-openvibe-visibility": [
++ "internal"
++ ],
++ "x-openvibe-quota-class": "notify",
++ "security": [
++ {
++ "openvibeToken": [
++ "network.operator.alert"
++ ]
++ }
++ ],
++ "requestBody": {
++ "required": false,
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.operator-alerts-request.v1"
++ }
++ }
++ }
++ },
++ "responses": {
++ "2XX": {
++ "description": "Success",
++ "content": {
++ "application/json": {
++ "schema": {
++ "$ref": "#/components/schemas/network.operator-alerts-result.v1"
++ }
++ }
++ }
++ },
++ "default": {
++ "description": "An error (RFC 9457 problem details)",
++ "content": {
++ "application/problem+json": {
++ "schema": {
++ "$ref": "#/components/schemas/errors.problem.v1"
++ }
++ }
++ }
++ }
++ }
++ }
}
},
"components": {
@@@ -1511,6 +1567,116 @@
}
]
},
++ "network.operator-alerts-request.v1": {
++ "title": "NetworkOperatorAlertsRequest",
++ "description": "network.operator-alerts-request@1: POST /internal/operator/alerts on OpenVibe.Network (capability network.operator.alert, held by the Host principal). The complete set of alerts firing now at one source: an alert Network has not seen firing opens and pages the operator; one still firing is reminded once a day; one that was firing and is absent from the set is resolved and says so. An empty list resolves everything from that source. Fingerprints are stable per alert (name and labels), never secrets; summaries and descriptions are the alert rule's annotations.",
++ "type": "object",
++ "required": [
++ "source",
++ "alerts"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "source": {
++ "enum": [
++ "prometheus"
++ ],
++ "description": "Where the alerts are evaluated. Resolution is per source."
++ },
++ "sent_at": {
++ "type": "string",
++ "format": "date-time"
++ },
++ "alerts": {
++ "type": "array",
++ "maxItems": 200,
++ "items": {
++ "type": "object",
++ "required": [
++ "fingerprint",
++ "name",
++ "severity",
++ "summary",
++ "started_at"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "fingerprint": {
++ "type": "string",
++ "pattern": "^[0-9a-f]{16,64}$"
++ },
++ "name": {
++ "type": "string",
++ "pattern": "^[A-Za-z][A-Za-z0-9_:]{0,99}$"
++ },
++ "severity": {
++ "enum": [
++ "critical",
++ "warning",
++ "info"
++ ]
++ },
++ "summary": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 300
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 1000
++ },
++ "service": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9-]{1,39}$"
++ },
++ "started_at": {
++ "type": "string",
++ "format": "date-time"
++ }
++ }
++ }
++ }
++ }
++ },
++ "network.operator-alerts-result.v1": {
++ "title": "NetworkOperatorAlertsResult",
++ "description": "network.operator-alerts-result@1: the answer of POST /internal/operator/alerts. firing: alerts firing after this report; opened: newly firing (paged); reminded: still firing and paged again (once a day); resolved: no longer firing (a resolved notice sent); notified: notifications created across all recipients (0 when no operator account is found or they switched admin notices off). Errors are { error } bodies (400 for a body that breaks the request contract).",
++ "type": "object",
++ "required": [
++ "ok",
++ "firing",
++ "opened",
++ "reminded",
++ "resolved",
++ "notified"
++ ],
++ "additionalProperties": false,
++ "properties": {
++ "ok": {
++ "const": true
++ },
++ "firing": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "opened": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "reminded": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "resolved": {
++ "type": "integer",
++ "minimum": 0
++ },
++ "notified": {
++ "type": "integer",
++ "minimum": 0
++ }
++ }
++ },
"network.staff-list-result.v1": {
"title": "NetworkStaffListResult",
"description": "network.staff-list-result@1: the answer of network.staff.read on OpenVibe.Network. GET /api/v1/staff/moderators[?service=chat|live|community|pastes|calls] (a service token holding network.staff.read, or a signed-in person holding staff.moderation.logs) → { service, staff }: the network's global moderators, admins and the owner who are not banned, with the staff capabilities their role holds in the contracts staff map; ?service keeps those holding the capability that moderates that service (another service name keeps those holding staff.content.moderate; an invalid value is ignored and answered as null). Answered with Cache-Control: private, no-store; a person without staff.moderation.logs gets 403 { error: forbidden }.",
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex 94d9ac7d..eaa13be9 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.61.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 e48ee1dc..89c57796 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRe.Stream API",
-- "version": "0.61.0",
-- "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenRe.Stream as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 dc965ad1..3ad22156 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.61.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 b9f98f65..ca3c2f5f 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.61.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 291fa826..79e74156 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.61.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 398fd94e..81825a00 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.61.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 74374033..86291b42 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.61.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 d55bb59b..ba4c70cf 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.61.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 4bbee77a..a258165c 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.61.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 7ba1fc62..bbc50591 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.61.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.61.0): each operation lists the capabilities it performs; a token for 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.62.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.62.0): each operation lists the capabilities it performs; a token for 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 d25a835a..7d0ec0a1 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -26111,6 +26111,43 @@ export type NetworkNotificationPushResult =
total: number;
};
++/** [email protected] (owner: network) */
++/**
++ * network.operator-alerts-request@1: POST /internal/operator/alerts on OpenVibe.Network (capability network.operator.alert, held by the Host principal). The complete set of alerts firing now at one source: an alert Network has not seen firing opens and pages the operator; one still firing is reminded once a day; one that was firing and is absent from the set is resolved and says so. An empty list resolves everything from that source. Fingerprints are stable per alert (name and labels), never secrets; summaries and descriptions are the alert rule's annotations.
++ */
++export interface NetworkOperatorAlertsRequest {
++ /**
++ * Where the alerts are evaluated. Resolution is per source.
++ */
++ source: "prometheus";
++ sent_at?: string;
++ /**
++ * @maxItems 200
++ */
++ alerts: {
++ fingerprint: string;
++ name: string;
++ severity: "critical" | "warning" | "info";
++ summary: string;
++ description?: string;
++ service?: string;
++ started_at: string;
++ }[];
++}
++
++/** [email protected] (owner: network) */
++/**
++ * network.operator-alerts-result@1: the answer of POST /internal/operator/alerts. firing: alerts firing after this report; opened: newly firing (paged); reminded: still firing and paged again (once a day); resolved: no longer firing (a resolved notice sent); notified: notifications created across all recipients (0 when no operator account is found or they switched admin notices off). Errors are { error } bodies (400 for a body that breaks the request contract).
++ */
++export interface NetworkOperatorAlertsResult {
++ ok: true;
++ firing: number;
++ opened: number;
++ reminded: number;
++ resolved: number;
++ notified: number;
++}
++
/** [email protected] (owner: network) */
/**
* What POST /api/v1/realtime/ticket answers (OpenVibe.Network; ADR-005 amendment 2): a realtime ticket (identity.realtime-ticket-claims@1) for the signed-in person, and where to use it. The caller is the person's own session (Bearer Network JWT, or the ov_token cookie on openvibe.network); guests are refused (403 realtime.guest), and 503 realtime.disabled means the operator turned browser realtime off (REALTIME_TICKETS=off): the client stays on polling. The client opens `${stream_url}?topics=${topics}&ticket=${ticket}` (plus last_event_id when it resumes) at once, and asks for a fresh ticket for every reconnect: a ticket opens one stream.
ddiff --git a/manifests/capabilities/network.operator.alert.json b/manifests/capabilities/network.operator.alert.json
nnew file mode 100644
iindex 00000000..260d6587
---- /dev/null
++++ b/manifests/capabilities/network.operator.alert.json
@@@ -0,0 +1,21 @@
++{
++ "id": "network.operator.alert",
++ "version": "1.0",
++ "owner": "network",
++ "status": "active",
++ "visibility": "internal",
++ "description": "Report the complete set of alerts firing on the production host, so Network pages the operator (the owner account) when an alert opens, once a day while it stays open, and when it resolves.",
++ "permissions": [
++ "notifications:write"
++ ],
++ "resourceConstraints": [
++ "none"
++ ],
++ "quotaClass": "notify",
++ "events": [],
++ "implementedBy": [
++ "POST /internal/operator/alerts"
++ ],
++ "inputSchema": "network.operator-alerts-request@1",
++ "outputSchema": "network.operator-alerts-result@1"
++}
ddiff --git a/manifests/services/network.json b/manifests/services/network.json
iindex 0a28532d..29f01b4b 100644
---- a/manifests/services/network.json
++++ b/manifests/services/network.json
@@@ -42,6 +42,7 @@
"network.modules.read",
"network.modules.write",
"network.notifications.push",
++ "network.operator.alert",
"network.project.manage",
"network.project.read",
"network.staff.read"
ddiff --git a/package.json b/package.json
iindex a5c79cc8..082bd377 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.61.0",
++ "version": "0.62.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",