openvibers/openvibe.live Commits

openvibe-shared v4.59.0 (was v4.57.1) (#479)

OP OpenVibers committed 13 days ago · a935ccad23 · 16 files, +37 −22

* openvibe-shared v4.59.0 (was v4.57.1)

Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v4.59.0 release.

* The Pair on Live: its logo files, the brand face from /shared, and the navbar's ring on page moves

- public/assets/logo*: the new mark (openvibe-shared/app-icon, the Pair; Live's record light in the O); the
  touch icon is the PNG (iOS takes no SVG).
- Live's own /shared route serves files.FONTS too (ov-brand.woff2, the names' face, as font/woff2).
- The home tour's mark is white on its lit disc (data-tone), and the thumbnail placeholder takes one muted colour.
- navigate() starts the navbar mark's page-load ring (OVMark.navStart) and it closes when the route has rendered
  (navEnd), at the pace this browser learned for Live's moves; a route without whenRouteReady closes it at once,
  and none waits past 8 s.

* The ring helpers live beside navigate(); the clip audit's fixtures are dated from today; Live's JS budget for 4.59.0

- stale-tab-release runs navigate() in a sandbox cut from app.js: the page-move ring helpers moved inside that span, and the sandbox has a timer.
- clip-audit-sql seeded its clips on fixed October days, and the audit counts the last 30 days: from 2026-10-31 the first fell out (2 !== 3). The clips are now created a few days before the run.
- jsRawKB 1242.7 measured with openvibe-shared 4.59.0 (the limit 1243).

* Every clip audit fixture is dated from today

The chat messages, the visits and the stream row were on fixed October days as well; the audit counts the last 30 days, so they fell out too.

Changes

ddiff --git a/README.md b/README.md
iindex ae9ca8e5..93fea6e0 100644
---- a/README.md
++++ b/README.md
@@@ -177,5 +177,5 @@ Minimum `.env`: `BASE_URL`, `JWT_SECRET`, `OV_NETWORK_URL`, `OV_NETWORK_INTERNAL
<!-- versions:start -->
- openvibe-contracts: v0.222.0
- openvibe-sdk: v0.74.0
--- openvibe-shared: v4.57.1
++- openvibe-shared: v4.59.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex 9c9ca975..23b38e35 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,7 +7,7 @@
"domain": "openvibe.live (www, ingest, whip)",
"contracts": "openvibe-contracts v0.222.0",
"sdk": "openvibe-sdk v0.74.0",
-- "shared": "openvibe-shared v4.57.1",
++ "shared": "openvibe-shared v4.59.0",
"capabilities": [
"live.chat_context.read",
"live.chat_effects.write",
ddiff --git a/package-lock.json b/package-lock.json
iindex 4ff21271..b97977fd 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -25,7 +25,7 @@
"onnxruntime-node": "^1.20.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.57.1",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.59.0",
"pg": "^8.23.1",
"sanitize-html": "^2.17.7",
"sdp-transform": "^3.0.0",
@@@ -2884,9 +2884,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "4.57.1",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.57.1",
-- "integrity": "sha512-zlU7F9H9E/5gqzklyGPJl7SH+WQ/+wn3e9Z7ErI3FbKxQ3caaVEGdZyX4Uww0PbvpgcXs2i6AnwNBi0JSOMlXQ==",
++ "version": "4.59.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.59.0",
++ "integrity": "sha512-kaJ6Tcz7WCewK/kCx4NzNWRNI4U1Z1lpwCQHWD115YtcaJps8Ulqpu1y2ArLpywARHtYf3ddPH/hL9wkb6MJlw==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0",
ddiff --git a/package.json b/package.json
iindex 47777d84..45e420ff 100644
---- a/package.json
++++ b/package.json
@@@ -44,7 +44,7 @@
"onnxruntime-node": "^1.20.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.57.1",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.59.0",
"pg": "^8.23.1",
"sanitize-html": "^2.17.7",
"sdp-transform": "^3.0.0",
ddiff --git a/public/assets/logo-192.png b/public/assets/logo-192.png
iindex 66927ec5..2bc614e2 100644
BBinary files a/public/assets/logo-192.png and b/public/assets/logo-192.png differ
ddiff --git a/public/assets/logo-512.png b/public/assets/logo-512.png
iindex 43fa2607..2db1e3c0 100644
BBinary files a/public/assets/logo-512.png and b/public/assets/logo-512.png differ
ddiff --git a/public/assets/logo-72.png b/public/assets/logo-72.png
iindex 310920cf..81a82baa 100644
BBinary files a/public/assets/logo-72.png and b/public/assets/logo-72.png differ
ddiff --git a/public/assets/logo-maskable-192.png b/public/assets/logo-maskable-192.png
iindex 2843580c..45f652b6 100644
BBinary files a/public/assets/logo-maskable-192.png and b/public/assets/logo-maskable-192.png differ
ddiff --git a/public/assets/logo-maskable-512.png b/public/assets/logo-maskable-512.png
iindex 5b2df8dc..1ab85b04 100644
BBinary files a/public/assets/logo-maskable-512.png and b/public/assets/logo-maskable-512.png differ
ddiff --git a/public/assets/logo.svg b/public/assets/logo.svg
iindex 63c22cd8..d1b4bd75 100644
---- a/public/assets/logo.svg
++++ b/public/assets/logo.svg
@@@ -1,8 +1,3 @@
--<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 -32 64 64"><defs><linearGradient id="ring" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#60a5fa"/><stop offset="1" stop-color="#2563eb"/></linearGradient>
--<radialGradient id="glow"><stop offset="0" stop-color="#60a5fa" stop-opacity=".34"/><stop offset="1" stop-color="#60a5fa" stop-opacity="0"/></radialGradient>
--<radialGradient id="bg" cx=".5" cy=".38" r=".8"><stop offset="0" stop-color="#16223a"/><stop offset=".6" stop-color="#0a0f1c"/><stop offset="1" stop-color="#060912"/></radialGradient></defs><rect x="-32" y="-32" width="64" height="64" rx="15" fill="url(#bg)"/><g transform="scale(1.22)">
--<circle r="21" fill="url(#glow)"/>
--<circle r="18" fill="none" stroke="url(#ring)" stroke-width="4" opacity=".38"/>
--<path d="M0,-18 A18,18 0 0,1 17.4,4.6" fill="none" stroke="url(#ring)" stroke-width="4.4" stroke-linecap="round"/>
--<path d="M-9.5,-7 L0,10 L9.5,-7" fill="none" stroke="#fff" stroke-width="4.8" stroke-linecap="round" stroke-linejoin="round"/>
--<circle cx="17.4" cy="4.6" r="3.2" fill="#ef4444"/></g></svg>
\\ No newline at end of file
++<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 -32 64 64"><defs><mask id="ovh" maskUnits="userSpaceOnUse" x="-20" y="-20" width="140" height="140"><rect x="-20" y="-20" width="140" height="140" fill="#fff"/><path d="M70.59 68.5L53.31 31.5M70.59 68.5L88.41 31.5" fill="none" stroke="#000" stroke-width="24" stroke-linecap="round"/></mask>
++<radialGradient id="glow"><stop offset="0" stop-color="#60a5fa" stop-opacity=".3"/><stop offset="1" stop-color="#60a5fa" stop-opacity="0"/></radialGradient>
++<radialGradient id="bg" cx=".5" cy=".38" r=".8"><stop offset="0" stop-color="#16223a"/><stop offset=".6" stop-color="#0a0f1c"/><stop offset="1" stop-color="#060912"/></radialGradient></defs><rect x="-32" y="-32" width="64" height="64" rx="15" fill="url(#bg)"/><g transform="scale(0.58) translate(-50 -50)"><ellipse cx="50" cy="50" rx="52" ry="40" fill="url(#glow)"/><circle cx="30.09" cy="50" r="18" fill="none" stroke="#4f7cff" stroke-width="18" mask="url(#ovh)"/><path d="M70.59 68.5L53.31 31.5M70.59 68.5L88.41 31.5" fill="none" stroke="#8b5cf6" stroke-width="17" stroke-linecap="round" stroke-linejoin="round"/><circle cx="30.09" cy="50" r="5.58" fill="#ef4444"/></g></svg>
\\ No newline at end of file
ddiff --git a/public/index.html b/public/index.html
iindex 8ff76e6c..a136ee69 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -37,7 +37,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="/assets/logo-192.png">
-- <link rel="apple-touch-icon" href="/assets/logo.svg">
++ <link rel="apple-touch-icon" href="/assets/logo-192.png">
<!-- Critical theme bootstrap (ov-theme-boot) — MUST stay inline and stay ABOVE the stylesheets.
Paints the user's cached theme synchronously, before the browser has any chance to
ddiff --git a/public/js/app.js b/public/js/app.js
iindex c00ec00b..5bf7fae7 100644
---- a/public/js/app.js
++++ b/public/js/app.js
@@@ -970,6 +970,19 @@ function sameSitePath(url) {
try { const u = new URL(url); return u.origin === location.origin ? `${u.pathname}${u.search}${u.hash}` : url; } catch { return url; }
}
++// The navbar's OpenVibe mark draws its ring round while one of Live's own page moves loads, at the pace this browser
++// learned for them, and closes it when the route has rendered (ov-mark.js, OVMark.navStart/navEnd). A route that
++// renders without whenRouteReady closes it after the move's own turn of the event loop; none waits past 8 s.
++let _ovNavSeq = 0, _ovNavOn = 0, _ovNavWaiting = false;
++function _ovNavStart() {
++ const me = _ovNavOn = ++_ovNavSeq;
++ _ovNavWaiting = false;
++ try { window.OVMark && window.OVMark.navStart('app'); } catch { /* */ }
++ setTimeout(() => { if (_ovNavOn === me && !_ovNavWaiting) _ovNavEnd(); }, 0);
++ setTimeout(() => { if (_ovNavOn === me) _ovNavEnd(); }, 8000);
++}
++function _ovNavEnd() { if (!_ovNavOn) return; _ovNavOn = 0; _ovNavWaiting = false; try { window.OVMark && window.OVMark.navEnd('app'); } catch { /* */ } }
++
function navigate(urlPath, replace = false) {
if (isOffSite(urlPath)) { if (replace) location.replace(urlPath); else location.href = urlPath; return; }
urlPath = sameSitePath(urlPath);
@@@ -980,6 +993,7 @@ function navigate(urlPath, replace = false) {
return;
}
teardownRoute(urlPath);
++ _ovNavStart();
// Normalize path
if (!urlPath.startsWith('/')) urlPath = '/' + urlPath;
@@@ -1057,10 +1071,13 @@ function whenRouteReady(pageId, render) {
console.error(`[route] ${path} failed to render:`, err);
if (window.ov) ov.showRouteError(`page-${pageId}`, err, () => whenRouteReady(pageId, render));
}
++ _ovNavEnd();
};
if (!window.ov) return run();
++ if (_ovNavOn) _ovNavWaiting = true;
ov.route(path).then(run, (err) => {
if (!ov.isCurrent(gen)) return;
++ _ovNavEnd();
ov.showRouteError(`page-${pageId}`, err, () => whenRouteReady(pageId, render));
});
}
@@@ -2087,7 +2104,7 @@ async function handleThumbnailError(img) {
function thumbImg(thumbnailUrl, fallbackIcon, alt, regenerateUrl = null) {
// The old brand glyph as a placeholder → the OV mark (static, muted).
const iconHtml = (extra) => fallbackIcon === 'fa-circle-nodes'
-- ? `<span class="ov-mark ov-mark--ph" data-size="44" data-static="1"${extra || ''}></span>`
++ ? `<span class="ov-mark ov-mark--ph" data-size="44" data-tone="ink" data-static="1"${extra || ''}></span>`
: `<i class="fa-solid ${fallbackIcon}"${extra || ''}></i>`;
if (thumbnailUrl) {
// openvibe.media thumbnails come in sizes (Media's /t/:id?w=&fmt=): a card loads a WebP near its width.
ddiff --git a/public/js/home-tour.js b/public/js/home-tour.js
iindex b0637189..10ea59ff 100644
---- a/public/js/home-tour.js
++++ b/public/js/home-tour.js
@@@ -59,7 +59,7 @@
<div class="tour-core-wrap">
<div class="tour-core" data-node="core">
<span class="tour-core-ring"></span><span class="tour-core-ring tour-core-ring--2"></span>
-- <span class="tour-core-logo"><span class="ov-mark" data-size="30" style="color:#fff"></span></span>
++ <span class="tour-core-logo"><span class="ov-mark" data-size="34" data-tone="white"></span></span>
<b>OpenVibe.Live</b>
<!-- The old feature line here ("<1s latency · chat · emotes · …") listed the same
things the chip grid below spells out properly. Two statements of the same
ddiff --git a/scripts/perf/check-budgets.js b/scripts/perf/check-budgets.js
iindex 33726e1f..8fa900c9 100644
---- a/scripts/perf/check-budgets.js
++++ b/scripts/perf/check-budgets.js
@@@ -22,7 +22,7 @@ const BUDGETS = {
htmlRawKB: 120, // measured 94.9
htmlBrotliKB: 30,
jsFiles: 26, // measured 23 (incl. route scripts for "/")
-- jsRawKB: 1240, // 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
++ jsRawKB: 1243, // 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
jsBrotliKB: 292, // 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)
cssRawKB: 270, // measured ~243 since the first-paint subset (style.core.css) replaced style.css (~717 before)
cssBrotliKB: 55, // measured ~47.5 (was ~130)
ddiff --git a/server/index.js b/server/index.js
iindex 79fc4900..09ddf12a 100644
---- a/server/index.js
++++ b/server/index.js
@@@ -595,8 +595,10 @@ console.log(`[Server] /shared: serving ${SHARED_BROWSER_FILES.length} browser fi
});
// The share cards (og:image on every page), before the browser-file allowlist below.
require('./web/share-cards').register(app);
-- // Serve only the whitelisted browser files — don't expose the entire package
-- const sharedFileSet = new Set(SHARED_BROWSER_FILES);
++ // Serve only the whitelisted browser files — don't expose the entire package — and the brand face the navbar
++ // declares beside itself (files.FONTS, Shared 4.59.0).
++ const SHARED_FONTS = sharedFiles.FONTS || [];
++ const sharedFileSet = new Set([...SHARED_BROWSER_FILES, ...SHARED_FONTS]);
app.use('/shared', (req, res, next) => {
const fileName = path.basename(req.path);
if (!sharedFileSet.has(fileName)) {
@@@ -609,7 +611,7 @@ console.log(`[Server] /shared: serving ${SHARED_BROWSER_FILES.length} browser fi
const hashed = Boolean(req.query.v) && req.query.v === assets.hashOf('/shared/' + fileName);
res.setHeader('Cache-Control', cache.assetHeaders(req.originalUrl, { hashed }));
if (hashed) res.setHeader('CDN-Cache-Control', cache.IMMUTABLE);
-- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
++ res.setHeader('Content-Type', SHARED_FONTS.includes(fileName) ? 'font/woff2' : 'application/javascript; charset=utf-8');
res.sendFile(filePath, (err) => {
// A listed file that cannot be read is this server's fault, and passing: never a cacheable answer
// (its headers above said immutable; Cloudflare kept a 404 navbar through a deploy on 2026-10-17).
ddiff --git a/test/stale-tab-release.test.js b/test/stale-tab-release.test.js
iindex 99cb03e4..62beb489 100644
---- a/test/stale-tab-release.test.js
++++ b/test/stale-tab-release.test.js
@@@ -47,6 +47,7 @@ function sandbox({ loaded = 'aaaaaaaaaaaa', current = 'bbbbbbbbbbbb', stored = n
},
sessionStorage: { getItem: (k) => (store.has(k) ? store.get(k) : null), setItem: (k, v) => store.set(k, String(v)) },
fetch: async (url) => { calls.push(['fetch', url]); return { ok: true, json: async () => ({ release: current }) }; },
++ setTimeout: () => 0,
teardownRoute: () => calls.push(['teardown']),
routeFromURL: () => calls.push(['route']),
};