openvibers/openvibe.network Commits

Track O: operator status and readiness. GET /status (server-rendered, noindex), /api/v1/status and /api/v1/status/slo; /api/ready with named checks; /metrics (loopback only) with token issuance by grant type and principal-token failures; the registry poll reads each service's readiness and /release.json and reports up|degraded|down|not-running|unknown, never a stale up; openvibe-shared v1.3.0. (Most of this change was swept into 89b67de by a concurrent commit; this adds the README section, the assigned ports of new services and one page fix.)

OP OpenVibers committed 23 Sept 2026 · bc74893621 · 3 files, +28 −1


Changes

ddiff --git a/README.md b/README.md
iindex 6b7af559..7cece48c 100644
---- a/README.md
++++ b/README.md
@@@ -260,6 +260,29 @@ Google-style account management supporting up to 5 accounts:
---
++## Observability and status
++
++- `GET /api/ready`: named checks from `openvibe-shared/ready`, each with `status`, `required`,
++ `latency_ms` and `checked_at`. `db` and `signing_key` are required (`signing_key` means an RS256
++ keypair that signs and verifies a probe token; it is only optional outside production).
++ `registry_poll` and `discord_bot` are optional. The answer is 503 only when a required check fails.
++ Otherwise it is 200, with `status: "degraded"` when an optional check has failed.
++- `GET /metrics`: Prometheus text for direct loopback callers only. Any proxied request gets a 404,
++ and `deploy/nginx` blocks the path too. Besides the HTTP golden signals by route template, it
++ exports process metrics and `release_info`. Network's own counters are
++ `network_tokens_issued_total{grant_type}`, `network_token_failures_total{grant_type,error}` and
++ `network_principal_token_failures_total{code}`.
++- `GET /status` is the operator page: server-rendered, no JavaScript needed, `noindex`.
++ `GET /api/v1/status` returns the same data as JSON. Each OpenVibe service shows as up, degraded,
++ down, not running (placeholder or no runtime) or unknown, with its release, boot time and
++ `checked_at`. The data comes from the ecosystem registry poll (`server/registry/ecosystem.js`),
++ which reads each service's readiness endpoint and `/release.json` about once a minute. A service
++ not checked yet, or whose last check is more than three intervals old, shows as unknown.
++- `GET /api/v1/status/slo` returns the proposed SLO categories, as does
++ [docs/slo.md](docs/slo.md) / [docs/slo.json](docs/slo.json).
++- [docs/patches/live-observability.diff](docs/patches/live-observability.diff) is the same change for
++ OpenVibe.Live, to be applied there.
++
## Shared Client Libraries
The `openvibe-shared` package ([OpenVibers/OpenVibe.Shared](https://github.com/OpenVibers/OpenVibe.Shared), pinned in package.json) provides drop-in vanilla JS components served at `/shared/` (and `/shared/v1/`). Only the package's browser files are served; a `?v=` equal to a file's content hash is cached for a year, anything else for five minutes:
ddiff --git a/server/registry/ecosystem.js b/server/registry/ecosystem.js
iindex 830c2df0..73b4f06f 100644
---- a/server/registry/ecosystem.js
++++ b/server/registry/ecosystem.js
@@@ -27,6 +27,11 @@ const INTERNAL = {
network: 'http://127.0.0.1:4000', live: 'http://127.0.0.1:3000', media: 'http://127.0.0.1:4100',
tools: 'http://127.0.0.1:4001', games: 'http://127.0.0.1:8000', community: 'http://127.0.0.1:4200',
events: 'http://127.0.0.1:4300', billing: 'http://127.0.0.1:4600',
++ // Assigned ports of services that are placeholders or new; a placeholder is never polled.
++ chat: 'http://127.0.0.1:4400', openre: 'http://127.0.0.1:4500', tips: 'http://127.0.0.1:4610', vip: 'http://127.0.0.1:4620',
++ ai: 'http://127.0.0.1:4700', search: 'http://127.0.0.1:4710', sources: 'http://127.0.0.1:4720', wiki: 'http://127.0.0.1:4800',
++ blog: 'http://127.0.0.1:4810', news: 'http://127.0.0.1:4820', reviews: 'http://127.0.0.1:4830', deals: 'http://127.0.0.1:4840',
++ coupons: 'http://127.0.0.1:4850', trade: 'http://127.0.0.1:4860', codes: 'http://127.0.0.1:4900', host: 'http://127.0.0.1:4910',
};
const POLL_MS = 60 * 1000;
// Readiness paths of services whose manifest (openvibe-contracts) does not carry `ready` yet. Each
ddiff --git a/server/status/routes.js b/server/status/routes.js
iindex 7bf2fabb..a3e0dbe5 100644
---- a/server/status/routes.js
++++ b/server/status/routes.js
@@@ -93,7 +93,6 @@ function renderPage(list, slo, generatedAt) {
<meta name="robots" content="noindex, nofollow">
${require('openvibe-shared/app-icon').headTags({ site: 'network', iconBase: '/assets' })}
<meta name="color-scheme" content="dark light">
--<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
<script src="/shared/theme-loader.js" defer></script>
<style>
*,*::before,*::after{box-sizing:border-box}