openvibers/openvibe.events Commits

Events: the retired events.openvibe.network vhost is deleted (plan T7) (#39)

OP OpenVibers committed 10 Oct 2026 · aed44d1923 · 7 files, +11 −54

Plan T7: "events.openvibe.network is deleted after the move." The move to openvibe.events is done. In nginx's logs the last service call to the old host was 2026-09-30 18:25 (a `node` client polling `/api/v1/events`); since then only crawlers have reached it.

This deletes `deploy/nginx/events.openvibe.network.conf` (the 308 redirect vhost) and updates the README, STATUS.json, `.env.example`, the config comment and the openvibe.events vhost header. `test/home.test.js` asserts the retired vhost is gone; 13/13 pass. Contracts 0.127.0 already dropped the domain from the registry. After the deploy, the vhost comes out of nginx on the host and the inventory names `openvibe.events.conf`.

Changes

ddiff --git a/.env.example b/.env.example
iindex 340a74c..a867cff 100644
---- a/.env.example
++++ b/.env.example
@@@ -11,8 +11,7 @@ HOST=127.0.0.1
NODE_ENV=development
# The API origin (plan T7): everything Events names about itself — Location headers, realtime URLs,
# limits.json links, llms.txt/sitemap, the home's examples — uses it; defaults to https://openvibe.events
--# in production, to http://localhost:PORT otherwise. events.openvibe.network answers until every client
--# moves, then redirects (308).
++# in production, to http://localhost:PORT otherwise.
#BASE_URL=https://openvibe.events
# The product origin; defaults to BASE_URL (openvibe.events is the API and product origin, plan T7).
#EVENTS_SITE_URL=https://openvibe.events
ddiff --git a/README.md b/README.md
iindex e153053..b114aa3 100644
---- a/README.md
++++ b/README.md
@@@ -3,7 +3,7 @@
> Durable events, subscriptions, delivery, retry, dead letters and replay for the network.
**Status:** alpha (roadmap Wave 3), deployed on `openvibe-ovh` (unit `openvibe-events`, 127.0.0.1:4300, public at `https://openvibe.events`). Live (`live.stream.*`), Media, Chat, Games, Network and OpenRestream publish to it in production, and every consumer webhook requires signature v2. Media's completion events reach Live through Events (`/internal/media-events`; Live keeps the older `/internal/media-webhook` during the transition), and the shared notification bell can follow `network.notification.created` over the realtime stream with a Network ticket.
--**Domain:** `openvibe.events` is the API and product origin (plan T7): the JSON API, the realtime gateway (ADR-005 put Realtime inside Events; `realtime.openvibe.network` has no runtime of its own), the home page and its `robots.txt`/`sitemap.xml`/`llms.txt`. `events.openvibe.network` answers 308 to the same path on openvibe.events.
++**Domain:** `openvibe.events` is the API and product origin (plan T7): the JSON API, the realtime gateway (ADR-005 put Realtime inside Events; `realtime.openvibe.network` has no runtime of its own), the home page and its `robots.txt`/`sitemap.xml`/`llms.txt`. The old `events.openvibe.network` address was retired on 2026-10-10.
**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §6 and §6.3.
**License:** AGPL-3.0 (same as every OpenVibe service).
@@@ -357,8 +357,8 @@ fast-forward `/opt/openvibe.events`, install on a lockfile change, restart, wait
The unit is `openvibe-events.service` on `127.0.0.1:4300`, the env file `/etc/openvibe/events.env`. The database is
`ov_events` on the host's data role (`sudo /opt/openvibe.host/roles/data/add-service.sh events` writes its settings); the
release migrates it at boot. nginx serves `openvibe.events`, the API and product origin, from
--[deploy/nginx/openvibe.events.conf](deploy/nginx/openvibe.events.conf); `events.openvibe.network` answers 308 to the
--same path there ([deploy/nginx/events.openvibe.network.conf](deploy/nginx/events.openvibe.network.conf)). ovhost treats open
++[deploy/nginx/openvibe.events.conf](deploy/nginx/openvibe.events.conf) (the old `events.openvibe.network` address was retired
++on 2026-10-10). ovhost treats open
realtime connections as a report-only drain, so `--wait-idle` waits for them.
Rollback: ovhost puts the previous sha back by itself when `/api/ready` does not answer 2xx after the
restart; afterwards `sudo ovhost rollback events --to <sha>`. Migrations only add tables and columns.
ddiff --git a/STATUS.json b/STATUS.json
iindex c766069..c58ac49 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -21,7 +21,7 @@
],
"capabilitiesRegistered": true,
"deployed": true,
-- "deployment": "Deployed with `sudo ovhost deploy events`: /opt/openvibe.events, unit openvibe-events, 127.0.0.1:4300; public at https://openvibe.events (plan T7: the API and product origin; realtime SSE, health, token-guarded /api/v1/events, /api/v1/subscriptions, /api/v1/checkpoints; /api/v1/deliveries host-local; events.openvibe.network answers the same surface until every client moves, then redirects 308); real traffic since 2026-09-23 (Live, Media, Chat, Games, Network and OpenRestream publish; on 2026-09-23 8 subscriptions, held by Search, Tips, VIP, News and Reviews); restore drill passed 2026-09-23",
++ "deployment": "Deployed with `sudo ovhost deploy events`: /opt/openvibe.events, unit openvibe-events, 127.0.0.1:4300; public at https://openvibe.events (plan T7: the API and product origin; realtime SSE, health, token-guarded /api/v1/events, /api/v1/subscriptions, /api/v1/checkpoints; /api/v1/deliveries host-local; the old events.openvibe.network address was retired on 2026-10-10); real traffic since 2026-09-23 (Live, Media, Chat, Games, Network and OpenRestream publish; on 2026-09-23 8 subscriptions, held by Search, Tips, VIP, News and Reviews); restore drill passed 2026-09-23",
"features": [
"durable event store with the canonical envelope",
"subscriptions with signed webhook delivery (v1 and v2), retry, dead letters and replay",
ddiff --git a/deploy/nginx/events.openvibe.network.conf b/deploy/nginx/events.openvibe.network.conf
ddeleted file mode 100644
iindex 0cf1c24..0000000
---- a/deploy/nginx/events.openvibe.network.conf
++++ /dev/null
@@@ -1,38 +0,0 @@
--## ═══════════════════════════════════════════════════════════════
--## events.openvibe.network — Nginx Configuration (REFERENCE)
--##
--## Deployed to /etc/nginx/sites-available/events.openvibe.network.conf — keep them in sync,
--## and reload nginx after changing it.
--##
--## OpenVibe.Events' API, realtime stream and product home are on https://openvibe.events
--## (deploy/nginx/openvibe.events.conf, plan T7). This old name answers 308 to the same path and query
--## there: a 308 keeps the method and the body, so a POST to /api/v1/events is replayed as a POST.
--## Services on this host never come through here: they call 127.0.0.1:4300 directly.
--## ═══════════════════════════════════════════════════════════════
--
--server {
-- listen 80;
-- listen [::]:80;
-- server_name events.openvibe.network;
--
-- location /.well-known/acme-challenge/ { root /var/www/certbot; }
-- location / { return 308 https://openvibe.events$request_uri; }
--}
--
--server {
-- listen 443 ssl;
-- listen [::]:443 ssl;
-- http2 on;
-- server_name events.openvibe.network;
--
-- ssl_certificate /etc/letsencrypt/live/openvibe.network/fullchain.pem;
-- ssl_certificate_key /etc/letsencrypt/live/openvibe.network/privkey.pem;
-- ssl_protocols TLSv1.2 TLSv1.3;
--
-- access_log /var/log/nginx/events.openvibe.network.access.log;
-- error_log /var/log/nginx/events.openvibe.network.error.log;
--
-- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
--
-- location / { return 308 https://openvibe.events$request_uri; }
--}
ddiff --git a/deploy/nginx/openvibe.events.conf b/deploy/nginx/openvibe.events.conf
iindex 1f7aecd..5297ae6 100644
---- a/deploy/nginx/openvibe.events.conf
++++ b/deploy/nginx/openvibe.events.conf
@@@ -6,9 +6,8 @@
##
## openvibe.events is the API and product origin (plan T7): the same Node service (port 4300,
## systemd unit openvibe-events) answers the product home and its discovery files, the
--## token-guarded JSON API, the realtime gateway and health, all here. events.openvibe.network
--## keeps answering the same surface unchanged (deploy/nginx/events.openvibe.network.conf) until
--## every client has moved; a later change turns it into a redirect (308) to this host.
++## token-guarded JSON API, the realtime gateway and health, all here. The old
++## events.openvibe.network address was retired on 2026-10-10 (its last service caller stopped 09-30).
##
## The Node service (port 4300) answers here:
## / the product home (server/home.js) for a browser, the text/plain API index otherwise
@@@ -26,7 +25,7 @@
## /internal/ host-local service endpoints, refused here
## ═══════════════════════════════════════════════════════════════
--# Distinct zone names: events.openvibe.network.conf declares its own and both files load in one config.
++# Zone names carry this site's prefix (ovevents_apex_*) so they never collide with another vhost's in one config.
limit_req_zone $binary_remote_addr zone=ovevents_apex_connect:10m rate=2r/s;
limit_conn_zone $binary_remote_addr zone=ovevents_apex_streams:10m;
limit_req_zone $binary_remote_addr zone=ovevents_apex_api:10m rate=20r/s;
ddiff --git a/server/config.js b/server/config.js
iindex 55aa2a0..d260cac 100644
---- a/server/config.js
++++ b/server/config.js
@@@ -81,8 +81,8 @@ function load(env = process.env) {
const port = int(env.PORT, 4300);
const maxInflight = int(env.EVENTS_MAX_INFLIGHT, 20);
const prefixes = sourcePrefixes(env);
-- // openvibe.events is the API origin and the product origin (plan T7); events.openvibe.network answers
-- // until every client moves, then redirects (308). Everything Events names about itself uses this.
++ // openvibe.events is the API origin and the product origin (plan T7; the old events.openvibe.network address was
++ // retired on 2026-10-10). Everything Events names about itself uses this.
const baseUrl = (env.BASE_URL || (isProduction ? 'https://openvibe.events' : `http://localhost:${port}`)).replace(/\/$/, '');
return {
port,
ddiff --git a/test/home.test.js b/test/home.test.js
iindex c15ed8d..d24ce4e 100644
---- a/test/home.test.js
++++ b/test/home.test.js
@@@ -166,10 +166,7 @@ t('deploy/nginx/openvibe.events.conf is the API and product origin, with no redi
assert.match(catchAll, /limit_except GET HEAD \{ deny all; \}/, 'the catch-all only passes GET and HEAD');
assert.match(catchAll, /proxy_pass http:\/\/127\.0\.0\.1:4300;/, 'and lets the app answer (favicon, 404 page)');
assert.ok(!/location \/ \{ return 404; \}/.test(conf), 'nginx\'s bare 404 page (no lang) is gone');
-- const old = fs.readFileSync(path.join(__dirname, '..', 'deploy', 'nginx', 'events.openvibe.network.conf'), 'utf8')
-- .split('\n').filter((l) => !/^\s*#/.test(l)).join('\n');
-- assert.ok(!old.includes('proxy_pass'), 'events.openvibe.network serves nothing itself');
-- assert.strictEqual((old.match(/return 308 https:\/\/openvibe\.events\$request_uri;/g) || []).length, 2, 'HTTP and HTTPS answer 308 to openvibe.events');
++ assert.ok(!fs.existsSync(path.join(__dirname, '..', 'deploy', 'nginx', 'events.openvibe.network.conf')), 'the retired events.openvibe.network vhost is gone (plan T7)');
assert.ok(conf.includes('return 301 https://openvibe.events$request_uri;'), ':80 and www reach the apex');
});