openvibers/openvibe.shared Commits

Shared 2.13.0: release-watch and the bell connect to openvibe.events (plan T7) (#24)

OP OpenVibers committed 7 Oct 2026 · 169f59b82f · 8 files, +17 −12

- [release-watch.js:192](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/release-watch.js:192): Default stream now uses `https://openvibe.events/realtime/stream`; configured URLs still take precedence.
- [README.md:386](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/README.md:386): Updated stream examples and CSP guidance; the bell still requires `https://openvibe.network` for tickets.
- [test/release-watch-realtime.test.js:14](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/test/release-watch-realtime.test.js:14): Updated default URL and CSP expectations.
- [test/notification-live.test.js:25](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/test/notification-live.test.js:25): Updated the ticket stream fixture and CSP expectation.
- [test/shipped.test.js:87](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/test/shipped.test.js:87): Added `openvibe.events` coverage; the existing hostname rule maps both Events names.
- [package.json:3](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/package.json:3): Set version to 2.13.0.
- [package-lock.json:3](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/package-lock.json:3): Set only the two root version entries to 2.13.0.
- [CHANGELOG.md:9](/tmp/claude-1000/-home-workstation-orca-workspaces-OpenVibe-Live-seadragon/070220df-455a-45d2-b679-8c15af458e9a/scratchpad/sh13-events/CHANGELOG.md:9): Added the dated 2.13.0 entry and CSP requirement.

**Ran:** `nice -n 15 ov test --no-cache` on the three requested tests and four additional release tests; all seven passed. `git diff --check` passed. `test/release.test.js` and `test/notification-live-chrome.test.js` could not complete because this sandbox rejects binding `127.0.0.1` (`EPERM`). No commit or push.

For Opus.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex d7ff22d..f6ff954 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -6,6 +6,10 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
## Unreleased
++## 2.13.0 — 2026-10-07
++
++- `release-watch` now connects to `https://openvibe.events` by default; the notification bell follows the stream URL in Network's ticket. A site pinning this release must allow `connect-src https://openvibe.events` in its CSP.
++
## 2.12.0 — 2026-10-07
- `showcase`: the sections (`.sc-hero`, `.sc-sec`, `.sc-cta`) set their own font stack (`--ov-font`, else Inter and
ddiff --git a/README.md b/README.md
iindex 50e25ed..854947d 100644
---- a/README.md
++++ b/README.md
@@@ -383,7 +383,7 @@ release.mount(app, { registry: m.registry }); // GET /release.json, POST /rele
- **Release notifications (1.17.0).** When OpenVibe.Host announces a release, it publishes
`host.release.published` (public, `ovhost deploy` / `ovhost announce`). release-watch opens one
EventSource per tab, without credentials, on
-- `https://events.openvibe.network/realtime/stream?topics=host.release.published`.
++ `https://openvibe.events/realtime/stream?topics=host.release.published`.
- **Which events count.** Only events whose `payload.service` is the page's service: `OVReleaseConfig.service`,
the meta tag's `data-service`, else the `service` of `/release.json`. The tab ignores the release it runs
or already knows (a hex prefix counts as the same release) and repeats of an event, and runs its usual
@@@ -402,7 +402,7 @@ release.mount(app, { registry: m.registry }); // GET /release.json, POST /rele
tag's `data-events` sets another URL, and `false` or `"off"` turns it off. Polling (focus, visibility,
every 10 minutes) is unchanged.
- **Origins.** Events answers `https://*.openvibe.*` origins, plus those in its `REALTIME_CORS_ORIGINS`.
-- - **CSP.** The site's CSP `connect-src` must allow `https://events.openvibe.network`. Otherwise the
++ - **CSP.** The site's CSP `connect-src` must allow `https://openvibe.events`. Otherwise the
browser refuses the stream once, and release-watch stops (state `blocked`) and keeps polling.
- **State.** `OVRelease.state().realtime` reports `{ state, service, url, events, ignored, checks, failures, lastSeq }`.
- **Metrics (D46)**: `release_client_updates_total{outcome,reason}`, where outcome is `prompted`
@@@ -496,14 +496,14 @@ can't load, those icons fall back to `<i class="fa-solid …">`. Two options cha
**The notification bell in realtime (1.22.0, off by default).** `OpenVibeNavbar.init({ notificationsRealtime: true })`, or `OpenVibeNotifications.init({ realtime: true })` where a site mounts the bell itself, makes the bell hear the person's new notifications as they happen. It uses Network's `network.notification.created` over OpenVibe.Events' realtime stream (ADR-005 amendment 2).
- **Loading.** notification-ui.js then loads `notification-live.js` from its own directory, so serve it beside notification-ui.js (it is in `files.js`).
--- **Each (re)connect.** It asks Network for a two-minute ticket (`POST https://openvibe.network/api/v1/realtime/ticket`) with the page's Bearer token, or with the session cookie on openvibe.network itself. It then opens `https://events.openvibe.network/realtime/stream?topics=network.notification.*&ticket=…` without credentials, resuming with `last_event_id`.
++- **Each (re)connect.** It asks Network for a two-minute ticket (`POST https://openvibe.network/api/v1/realtime/ticket`) with the page's Bearer token, or with the session cookie on openvibe.network itself. It then opens the ticket's stream URL (now `https://openvibe.events/realtime/stream?topics=network.notification.*&ticket=…`) without credentials, resuming with `last_event_id`.
- **What it reacts to.** On an event whose subject is the person, it re-reads the unread count and toasts what is new: one request per burst. On `event: gap` it also reloads the open lists.
- **Polling stays:** every 15 s without a stream, and every 2 min while the stream is open, as a safety net for reads made on other sites.
- **Retries and giving up.**
- Errors back off from 2 s, with jitter. After ten failures in a row the bell polls only, until the browser comes back `online`.
- A tab hidden 5 minutes closes the stream and resumes it when shown.
- A Content-Security-Policy refusal, a signed-out 401/403, or Network's `REALTIME_TICKETS=off` (503) stop the stream, and the bell polls.
--- **The site's CSP** needs `connect-src https://events.openvibe.network` (and `https://openvibe.network` for the ticket, which the bell already calls). `OpenVibeNotifications.realtimeState()` reports the feed's state.
++- **The site's CSP** needs `connect-src https://openvibe.events` (and `https://openvibe.network` for the ticket, which the bell already calls). `OpenVibeNotifications.realtimeState()` reports the feed's state.
### Boost (`boost.js`): smooth page moves for a server-rendered site
ddiff --git a/package-lock.json b/package-lock.json
iindex da8eec1..c958738 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-shared",
-- "version": "2.12.0",
++ "version": "2.13.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-shared",
-- "version": "2.12.0",
++ "version": "2.13.0",
"license": "MIT",
"bin": {
"openvibe-build-assets": "scripts/build-assets.js"
ddiff --git a/package.json b/package.json
iindex aae1302..c77dbe6 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-shared",
-- "version": "2.12.0",
++ "version": "2.13.0",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"bin": {
ddiff --git a/release-watch.js b/release-watch.js
iindex cba1cd8..2f3b5ae 100644
---- a/release-watch.js
++++ b/release-watch.js
@@@ -189,7 +189,7 @@
function eventsUrl() {
const v = 'eventsUrl' in cfg ? cfg.eventsUrl : meta && meta.hasAttribute('data-events') ? meta.getAttribute('data-events') : undefined;
if (v !== undefined) return v && v !== 'off' ? String(v) : null;
-- try { return new URL(root.location.href).protocol === 'https:' ? 'https://events.openvibe.network/realtime/stream' : null; } catch { return null; }
++ try { return new URL(root.location.href).protocol === 'https:' ? 'https://openvibe.events/realtime/stream' : null; } catch { return null; }
}
function live() {
if (stopped || es || rt.state !== 'off' || typeof root.EventSource !== 'function') return;
ddiff --git a/test/notification-live.test.js b/test/notification-live.test.js
iindex ed57746..5023df3 100644
---- a/test/notification-live.test.js
++++ b/test/notification-live.test.js
@@@ -22,7 +22,7 @@ const UI_SRC = fs.readFileSync(path.join(ROOT, 'notification-ui.js'), 'utf8');
const ALICE = 'usr_01JAB2C3D4E5F6G7H8J9K0MNPQ';
const BOB = 'usr_01JAB2C3D4E5F6G7H8J9K0MNPR';
const API = 'https://openvibe.network';
--const STREAM = 'https://events.openvibe.network/realtime/stream';
++const STREAM = 'https://openvibe.events/realtime/stream';
function page({ url = 'https://openvibe.live/', eventSource = true, random = 0.5 } = {}) {
const { window: lw, document } = linkedom.parseHTML('<!doctype html><html><head></head><body></body></html>');
@@@ -205,7 +205,7 @@ const created = (subject, over = {}) => ({
// A Content-Security-Policy refusal of Events: closed, and nothing reopens it.
const s4 = p.es;
-- p.csp('https://events.openvibe.network/realtime/stream');
++ p.csp('https://openvibe.events/realtime/stream');
assert.deepStrictEqual([s4.closed, live.state().state], [true, 'blocked']);
s4.fail(); p.dispatch('online'); await p.settle();
assert.strictEqual(live.state().state, 'blocked');
ddiff --git a/test/release-watch-realtime.test.js b/test/release-watch-realtime.test.js
iindex c8edee2..6f1ad35 100644
---- a/test/release-watch-realtime.test.js
++++ b/test/release-watch-realtime.test.js
@@@ -11,7 +11,7 @@ const vm = require('vm');
const { openPage, manifestFor } = require('../release-compat');
const A = 'aaaaaaa1'; const B = 'bbbbbbb2'; const C = 'ccccccc3';
--const DEFAULT = 'https://events.openvibe.network/realtime/stream';
++const DEFAULT = 'https://openvibe.events/realtime/stream';
const PAGE = (attrs = '') => `<!doctype html><html><head><meta name="ov-release" content="${A}" data-url="/release.json"${attrs}></head><body></body></html>`;
function fakeEventSource() {
@@@ -187,7 +187,7 @@ async function open({ url = 'https://openvibe.live/', html = PAGE(), config = nu
p.document.dispatchEvent(v);
assert.strictEqual(p.rt().state, 'connecting', 'another URL\'s violation is not ours');
const mine = new p.window.Event('securitypolicyviolation');
-- mine.blockedURI = 'https://events.openvibe.network';
++ mine.blockedURI = 'https://openvibe.events';
p.document.dispatchEvent(mine);
s.fail();
assert.deepStrictEqual([s.closed, p.rt().state, p.timeouts()], [true, 'blocked', []], 'no retry');
ddiff --git a/test/shipped.test.js b/test/shipped.test.js
iindex f4a30c2..6924a3c 100644
---- a/test/shipped.test.js
++++ b/test/shipped.test.js
@@@ -84,6 +84,7 @@ const data = {
assert.strictEqual(sf('pdf.openvibe.tools'), 'tools');
assert.strictEqual(sf('my.openvibe.network'), 'network');
assert.strictEqual(sf('events.openvibe.network'), 'events');
++ assert.strictEqual(sf('openvibe.events'), 'events');
assert.strictEqual(sf('ingest.openre.stream'), 'openre');
assert.strictEqual(sf('openvibe.bot'), 'bot', 'OpenVibe.Bot is a site');
assert.strictEqual(sf('bot'), 'bot');